summaryrefslogtreecommitdiff
path: root/Drivers/STM32H7xx_HAL_Driver/Src
diff options
context:
space:
mode:
authorozpv <39195175+ozpv@users.noreply.github.com>2026-08-15 17:18:25 -0500
committerozpv <39195175+ozpv@users.noreply.github.com>2026-08-15 17:18:25 -0500
commit091a130d655e75bb4d5f24a15883206869e43aa7 (patch)
treec7b86f285560851c89b240e2194695e1ef662d67 /Drivers/STM32H7xx_HAL_Driver/Src
parent8ca3415eff99aaadd0c555053fd6c03e6a3cb9b1 (diff)
Add files via git push
Diffstat (limited to 'Drivers/STM32H7xx_HAL_Driver/Src')
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c1312
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c558
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c2059
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c712
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c865
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c1276
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c2129
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c556
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c447
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c7528
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c372
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c1899
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nand.c2199
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nor.c1642
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c2347
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c341
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c876
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c2158
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c2752
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c1814
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c3935
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai.c2946
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai_ex.c134
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sdram.c1314
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sram.c1118
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c7973
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c2921
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_delayblock.c214
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c1090
-rwxr-xr-xDrivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c2344
30 files changed, 57831 insertions, 0 deletions
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c
new file mode 100755
index 0000000..820fc09
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal.c
@@ -0,0 +1,1312 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal.c
+ * @author MCD Application Team
+ * @brief HAL module driver.
+ * This is the common part of the HAL initialization
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The common HAL driver contains a set of generic and common APIs that can be
+ used by the PPP peripheral drivers and the user to start using the HAL.
+ [..]
+ The HAL contains two APIs' categories:
+ (+) Common HAL APIs
+ (+) Services HAL APIs
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup HAL HAL
+ * @brief HAL module driver.
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/**
+ * @brief STM32H7xx HAL Driver version number
+ */
+#define __STM32H7xx_HAL_VERSION_MAIN (0x01UL) /*!< [31:24] main version */
+#define __STM32H7xx_HAL_VERSION_SUB1 (0x0BUL) /*!< [23:16] sub1 version */
+#define __STM32H7xx_HAL_VERSION_SUB2 (0x06UL) /*!< [15:8] sub2 version */
+#define __STM32H7xx_HAL_VERSION_RC (0x00UL) /*!< [7:0] release candidate */
+#define __STM32H7xx_HAL_VERSION ((__STM32H7xx_HAL_VERSION_MAIN << 24)\
+ |(__STM32H7xx_HAL_VERSION_SUB1 << 16)\
+ |(__STM32H7xx_HAL_VERSION_SUB2 << 8 )\
+ |(__STM32H7xx_HAL_VERSION_RC))
+
+#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF)
+#define VREFBUF_TIMEOUT_VALUE (uint32_t)10 /* 10 ms */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Exported variables --------------------------------------------------------*/
+
+/** @defgroup HAL_Exported_Variables HAL Exported Variables
+ * @{
+ */
+__IO uint32_t uwTick;
+uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* Invalid PRIO */
+HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
+/**
+ * @}
+ */
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @addtogroup HAL_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup HAL_Group1
+ * @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:
+ * 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
+ * "stm32h7xx_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)
+{
+
+uint32_t common_system_clock;
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ /* Configure Cortex-M4 Instruction cache through ART accelerator */
+ __HAL_RCC_ART_CLK_ENABLE(); /* Enable the Cortex-M4 ART Clock */
+ __HAL_ART_CONFIG_BASE_ADDRESS(0x08100000UL); /* Configure the Cortex-M4 ART Base address to the Flash Bank 2 : */
+ __HAL_ART_ENABLE(); /* Enable the Cortex-M4 ART */
+#endif /* DUAL_CORE && CORE_CM4 */
+
+ /* Set Interrupt Group Priority */
+ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
+
+ /* Update the SystemCoreClock global variable */
+#if defined(RCC_D1CFGR_D1CPRE)
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos]) & 0x1FU);
+#else
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE)>> RCC_CDCFGR1_CDCPRE_Pos]) & 0x1FU);
+#endif
+
+ /* Update the SystemD2Clock global variable */
+#if defined(RCC_D1CFGR_HPRE)
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
+#else
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
+#endif
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ SystemCoreClock = SystemD2Clock;
+#else
+ SystemCoreClock = common_system_clock;
+#endif /* DUAL_CORE && CORE_CM4 */
+
+ /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
+ if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* 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_AHB3_FORCE_RESET();
+ __HAL_RCC_AHB3_RELEASE_RESET();
+
+ __HAL_RCC_AHB1_FORCE_RESET();
+ __HAL_RCC_AHB1_RELEASE_RESET();
+
+ __HAL_RCC_AHB2_FORCE_RESET();
+ __HAL_RCC_AHB2_RELEASE_RESET();
+
+ __HAL_RCC_AHB4_FORCE_RESET();
+ __HAL_RCC_AHB4_RELEASE_RESET();
+
+ __HAL_RCC_APB3_FORCE_RESET();
+ __HAL_RCC_APB3_RELEASE_RESET();
+
+ __HAL_RCC_APB1L_FORCE_RESET();
+ __HAL_RCC_APB1L_RELEASE_RESET();
+
+ __HAL_RCC_APB1H_FORCE_RESET();
+ __HAL_RCC_APB1H_RELEASE_RESET();
+
+ __HAL_RCC_APB2_FORCE_RESET();
+ __HAL_RCC_APB2_RELEASE_RESET();
+
+ __HAL_RCC_APB4_FORCE_RESET();
+ __HAL_RCC_APB4_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 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)
+{
+ /* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
+ if((uint32_t)uwTickFreq == 0UL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Configure the SysTick to have interrupt in 1ms time basis*/
+ if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) > 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Configure the SysTick IRQ priority */
+ if (TickPriority < (1UL << __NVIC_PRIO_BITS))
+ {
+ HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
+ uwTickPrio = TickPriority;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup HAL_Group2
+ * @brief HAL Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### HAL Control functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Provide a tick value in millisecond
+ (+) Provide a blocking delay in millisecond
+ (+) Suspend the time base source interrupt
+ (+) Resume the time base source interrupt
+ (+) Get the HAL API driver version
+ (+) Get the device 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 += (uint32_t)uwTickFreq;
+}
+
+/**
+ * @brief Provides a tick value in millisecond.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval tick value
+ */
+__weak uint32_t HAL_GetTick(void)
+{
+ return uwTick;
+}
+
+/**
+ * @brief This function returns a tick priority.
+ * @retval tick priority
+ */
+uint32_t HAL_GetTickPrio(void)
+{
+ return uwTickPrio;
+}
+
+/**
+ * @brief Set new tick Freq.
+ * @retval Status
+ */
+HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_TickFreqTypeDef prevTickFreq;
+
+ assert_param(IS_TICKFREQ(Freq));
+
+ if (uwTickFreq != Freq)
+ {
+
+ /* Back up uwTickFreq frequency */
+ prevTickFreq = uwTickFreq;
+
+ /* Update uwTickFreq global variable used by HAL_InitTick() */
+ uwTickFreq = Freq;
+
+ /* Apply the new tick Freq */
+ status = HAL_InitTick(uwTickPrio);
+ if (status != HAL_OK)
+ {
+ /* Restore previous tick frequency */
+ uwTickFreq = prevTickFreq;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Return tick frequency.
+ * @retval Tick frequency.
+ * Value of @ref HAL_TickFreqTypeDef.
+ */
+HAL_TickFreqTypeDef HAL_GetTickFreq(void)
+{
+ return uwTickFreq;
+}
+
+/**
+ * @brief This function provides minimum delay (in milliseconds) based
+ * on variable incremented.
+ * @note In the default implementation , SysTick timer is the source of time base.
+ * It is used to generate interrupts at regular time intervals where uwTick
+ * is incremented.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @param Delay specifies the delay time length, in milliseconds.
+ * @retval None
+ */
+__weak void HAL_Delay(uint32_t Delay)
+{
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t wait = Delay;
+
+ /* Add a freq to guarantee minimum wait */
+ if (wait < HAL_MAX_DELAY)
+ {
+ wait += (uint32_t)(uwTickFreq);
+ }
+
+ while ((HAL_GetTick() - tickstart) < wait)
+ {
+ }
+}
+
+/**
+ * @brief Suspend Tick increment.
+ * @note In the default implementation , SysTick timer is the source of time base. It is
+ * used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
+ * is called, the SysTick interrupt will be disabled and so Tick increment
+ * is suspended.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_SuspendTick(void)
+{
+ /* Disable SysTick Interrupt */
+ SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
+}
+
+/**
+ * @brief Resume Tick increment.
+ * @note In the default implementation , SysTick timer is the source of time base. It is
+ * used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
+ * is called, the SysTick interrupt will be enabled and so Tick increment
+ * is resumed.
+ * @note This function is declared as __weak to be overwritten in case of other
+ * implementations in user file.
+ * @retval None
+ */
+__weak void HAL_ResumeTick(void)
+{
+ /* Enable SysTick Interrupt */
+ SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
+}
+
+/**
+ * @brief Returns the HAL revision
+ * @retval version : 0xXYZR (8bits for each decimal, R for RC)
+ */
+uint32_t HAL_GetHalVersion(void)
+{
+ return __STM32H7xx_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 Return the first word of the unique device identifier (UID based on 96 bits)
+ * @retval Device identifier
+ */
+uint32_t HAL_GetUIDw0(void)
+{
+ return(READ_REG(*((uint32_t *)UID_BASE)));
+}
+
+/**
+ * @brief Return the second word of the unique device identifier (UID based on 96 bits)
+ * @retval Device identifier
+ */
+uint32_t HAL_GetUIDw1(void)
+{
+ return(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
+}
+
+/**
+ * @brief Return the third word of the unique device identifier (UID based on 96 bits)
+ * @retval Device identifier
+ */
+uint32_t HAL_GetUIDw2(void)
+{
+ return(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
+}
+
+/**
+ * @brief Configure the internal voltage reference buffer voltage scale.
+ * @param VoltageScaling specifies the output voltage to achieve
+ * This parameter can be one of the following values:
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE0: VREF_OUT1 around 2.5 V.
+ * This requires VDDA equal to or higher than 2.8 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE1: VREF_OUT2 around 2.048 V.
+ * This requires VDDA equal to or higher than 2.4 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE2: VREF_OUT3 around 1.8 V.
+ * This requires VDDA equal to or higher than 2.1 V.
+ * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE3: VREF_OUT4 around 1.5 V.
+ * This requires VDDA equal to or higher than 1.8 V.
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(VoltageScaling));
+
+ MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_VRS, VoltageScaling);
+}
+
+/**
+ * @brief Configure the internal voltage reference buffer high impedance mode.
+ * @param Mode specifies the high impedance mode
+ * This parameter can be one of the following values:
+ * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE: VREF+ pin is internally connect to VREFINT output.
+ * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE: VREF+ pin is high impedance.
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(Mode));
+
+ MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_HIZ, Mode);
+}
+
+/**
+ * @brief Tune the Internal Voltage Reference buffer (VREFBUF).
+ * @retval None
+ */
+void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue));
+
+ MODIFY_REG(VREFBUF->CCR, VREFBUF_CCR_TRIM, TrimmingValue);
+}
+
+/**
+ * @brief Enable the Internal Voltage Reference buffer (VREFBUF).
+ * @retval HAL_OK/HAL_TIMEOUT
+ */
+HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void)
+{
+ uint32_t tickstart;
+
+ SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait for VRR bit */
+ while(READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == 0UL)
+ {
+ if((HAL_GetTick() - tickstart) > VREFBUF_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Internal Voltage Reference buffer (VREFBUF).
+ *
+ * @retval None
+ */
+void HAL_SYSCFG_DisableVREFBUF(void)
+{
+ CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR);
+}
+
+#if defined(SYSCFG_PMCR_EPIS_SEL)
+/**
+ * @brief Ethernet PHY Interface Selection either MII or RMII
+ * @param SYSCFG_ETHInterface: Selects the Ethernet PHY interface
+ * This parameter can be one of the following values:
+ * @arg SYSCFG_ETH_MII : Select the Media Independent Interface
+ * @arg SYSCFG_ETH_RMII: Select the Reduced Media Independent Interface
+ * @retval None
+ */
+void HAL_SYSCFG_ETHInterfaceSelect(uint32_t SYSCFG_ETHInterface)
+{
+ /* Check the parameter */
+ assert_param(IS_SYSCFG_ETHERNET_CONFIG(SYSCFG_ETHInterface));
+
+ MODIFY_REG(SYSCFG->PMCR, SYSCFG_PMCR_EPIS_SEL, (uint32_t)(SYSCFG_ETHInterface));
+}
+#endif /* SYSCFG_PMCR_EPIS_SEL */
+
+/**
+ * @brief Analog Switch control for dual analog pads.
+ * @param SYSCFG_AnalogSwitch: Selects the analog pad
+ * This parameter can be one or a combination of the following values:
+ * @arg SYSCFG_SWITCH_PA0 : Select PA0 analog switch
+ * @arg SYSCFG_SWITCH_PA1: Select PA1 analog switch
+ * @arg SYSCFG_SWITCH_PC2 : Select PC2 analog switch
+ * @arg SYSCFG_SWITCH_PC3: Select PC3 analog switch
+ * @param SYSCFG_SwitchState: Open or Close the analog switch between dual pads (PXn and PXn_C)
+ * This parameter can be one or a combination of the following values:
+ * @arg SYSCFG_SWITCH_PA0_OPEN
+ * @arg SYSCFG_SWITCH_PA0_CLOSE
+ * @arg SYSCFG_SWITCH_PA1_OPEN
+ * @arg SYSCFG_SWITCH_PA1_CLOSE
+ * @arg SYSCFG_SWITCH_PC2_OPEN
+ * @arg SYSCFG_SWITCH_PC2_CLOSE
+ * @arg SYSCFG_SWITCH_PC3_OPEN
+ * @arg SYSCFG_SWITCH_PC3_CLOSE
+ * @retval None
+ */
+
+void HAL_SYSCFG_AnalogSwitchConfig(uint32_t SYSCFG_AnalogSwitch , uint32_t SYSCFG_SwitchState )
+{
+ /* Check the parameter */
+ assert_param(IS_SYSCFG_ANALOG_SWITCH(SYSCFG_AnalogSwitch));
+ assert_param(IS_SYSCFG_SWITCH_STATE(SYSCFG_SwitchState));
+
+ MODIFY_REG(SYSCFG->PMCR, (uint32_t) SYSCFG_AnalogSwitch, (uint32_t)(SYSCFG_SwitchState));
+}
+
+#if defined(SYSCFG_PMCR_BOOSTEN)
+/**
+ * @brief Enables the booster to reduce the total harmonic distortion of the analog
+ * switch when the supply voltage is lower than 2.7 V.
+ * @note Activating the booster allows to guaranty the analog switch AC performance
+ * when the supply voltage is below 2.7 V: in this case, the analog switch
+ * performance is the same on the full voltage range
+ * @retval None
+ */
+void HAL_SYSCFG_EnableBOOST(void)
+{
+ SET_BIT(SYSCFG->PMCR, SYSCFG_PMCR_BOOSTEN) ;
+}
+
+/**
+ * @brief Disables the booster
+ * @note Activating the booster allows to guaranty the analog switch AC performance
+ * when the supply voltage is below 2.7 V: in this case, the analog switch
+ * performance is the same on the full voltage range
+ * @retval None
+ */
+void HAL_SYSCFG_DisableBOOST(void)
+{
+ CLEAR_BIT(SYSCFG->PMCR, SYSCFG_PMCR_BOOSTEN) ;
+}
+#endif /* SYSCFG_PMCR_BOOSTEN */
+
+#if defined (SYSCFG_UR2_BOOT_ADD0) || defined (SYSCFG_UR2_BCM7_ADD0)
+/**
+ * @brief BootCM7 address 0 configuration
+ * @param BootRegister :Specifies the Boot Address register (Address0 or Address1)
+ * This parameter can be one of the following values:
+ * @arg SYSCFG_BOOT_ADDR0 : Select the boot address0
+ * @arg SYSCFG_BOOT_ADDR1: Select the boot address1
+ * @param BootAddress :Specifies the CM7 Boot Address to be loaded in Address0 or Address1
+ * @retval None
+ */
+void HAL_SYSCFG_CM7BootAddConfig(uint32_t BootRegister, uint32_t BootAddress)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_BOOT_REGISTER(BootRegister));
+ assert_param(IS_SYSCFG_BOOT_ADDRESS(BootAddress));
+ if ( BootRegister == SYSCFG_BOOT_ADDR0 )
+ {
+ /* Configure CM7 BOOT ADD0 */
+#if defined(DUAL_CORE)
+ MODIFY_REG(SYSCFG->UR2, SYSCFG_UR2_BCM7_ADD0, ((BootAddress >> 16) << SYSCFG_UR2_BCM7_ADD0_Pos));
+#else
+ MODIFY_REG(SYSCFG->UR2, SYSCFG_UR2_BOOT_ADD0, ((BootAddress >> 16) << SYSCFG_UR2_BOOT_ADD0_Pos));
+#endif /*DUAL_CORE*/
+ }
+ else
+ {
+ /* Configure CM7 BOOT ADD1 */
+#if defined(DUAL_CORE)
+ MODIFY_REG(SYSCFG->UR3, SYSCFG_UR3_BCM7_ADD1, (BootAddress >> 16));
+#else
+ MODIFY_REG(SYSCFG->UR3, SYSCFG_UR3_BOOT_ADD1, (BootAddress >> 16));
+#endif /*DUAL_CORE*/
+ }
+}
+#endif /* SYSCFG_UR2_BOOT_ADD0 || SYSCFG_UR2_BCM7_ADD0 */
+
+#if defined(DUAL_CORE)
+/**
+ * @brief BootCM4 address 0 configuration
+ * @param BootRegister :Specifies the Boot Address register (Address0 or Address1)
+ * This parameter can be one of the following values:
+ * @arg SYSCFG_BOOT_ADDR0 : Select the boot address0
+ * @arg SYSCFG_BOOT_ADDR1: Select the boot address1
+ * @param BootAddress :Specifies the CM4 Boot Address to be loaded in Address0 or Address1
+ * @retval None
+ */
+void HAL_SYSCFG_CM4BootAddConfig(uint32_t BootRegister, uint32_t BootAddress)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_BOOT_REGISTER(BootRegister));
+ assert_param(IS_SYSCFG_BOOT_ADDRESS(BootAddress));
+
+ if ( BootRegister == SYSCFG_BOOT_ADDR0 )
+ {
+ /* Configure CM4 BOOT ADD0 */
+ MODIFY_REG(SYSCFG->UR3, SYSCFG_UR3_BCM4_ADD0, ((BootAddress >> 16)<< SYSCFG_UR3_BCM4_ADD0_Pos));
+ }
+
+ else
+ {
+ /* Configure CM4 BOOT ADD1 */
+ MODIFY_REG(SYSCFG->UR4, SYSCFG_UR4_BCM4_ADD1, (BootAddress >> 16));
+ }
+}
+
+/**
+ * @brief Enables the Cortex-M7 boot
+ * @retval None
+ */
+void HAL_SYSCFG_EnableCM7BOOT(void)
+{
+ SET_BIT(SYSCFG->UR1, SYSCFG_UR1_BCM7);
+}
+
+/**
+ * @brief Disables the Cortex-M7 boot
+ * @note Disabling the boot will gate the CPU clock
+ * @retval None
+ */
+void HAL_SYSCFG_DisableCM7BOOT(void)
+{
+ CLEAR_BIT(SYSCFG->UR1, SYSCFG_UR1_BCM7) ;
+}
+
+/**
+ * @brief Enables the Cortex-M4 boot
+ * @retval None
+ */
+void HAL_SYSCFG_EnableCM4BOOT(void)
+{
+ SET_BIT(SYSCFG->UR1, SYSCFG_UR1_BCM4);
+}
+
+/**
+ * @brief Disables the Cortex-M4 boot
+ * @note Disabling the boot will gate the CPU clock
+ * @retval None
+ */
+void HAL_SYSCFG_DisableCM4BOOT(void)
+{
+ CLEAR_BIT(SYSCFG->UR1, SYSCFG_UR1_BCM4);
+}
+#endif /*DUAL_CORE*/
+/**
+ * @brief Enables the I/O Compensation Cell.
+ * @note The I/O compensation cell can be used only when the device supply
+ * voltage ranges from 1.62 to 2.0 V and from 2.7 to 3.6 V.
+ * @retval None
+ */
+void HAL_EnableCompensationCell(void)
+{
+ SET_BIT(SYSCFG->CCCSR, SYSCFG_CCCSR_EN) ;
+}
+
+/**
+ * @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 1.62 to 2.0 V and from 2.7 to 3.6 V.
+ * @retval None
+ */
+void HAL_DisableCompensationCell(void)
+{
+ CLEAR_BIT(SYSCFG->CCCSR, SYSCFG_CCCSR_EN);
+}
+
+
+/**
+ * @brief To Enable optimize the I/O speed when the product voltage is low.
+ * @note This bit is active only if PRODUCT_BELOW_25V user option bit is set. It must be
+ * used only if the product supply voltage is below 2.5 V. Setting this bit when VDD is
+ * higher than 2.5 V might be destructive.
+ * @retval None
+ */
+void HAL_SYSCFG_EnableIOSpeedOptimize(void)
+{
+#if defined(SYSCFG_CCCSR_HSLV)
+ SET_BIT(SYSCFG->CCCSR, SYSCFG_CCCSR_HSLV);
+#else
+ SET_BIT(SYSCFG->CCCSR, (SYSCFG_CCCSR_HSLV0| SYSCFG_CCCSR_HSLV1 | SYSCFG_CCCSR_HSLV2 | SYSCFG_CCCSR_HSLV3));
+#endif /* SYSCFG_CCCSR_HSLV */
+}
+
+/**
+ * @brief To Disable optimize the I/O speed when the product voltage is low.
+ * @note This bit is active only if PRODUCT_BELOW_25V user option bit is set. It must be
+ * used only if the product supply voltage is below 2.5 V. Setting this bit when VDD is
+ * higher than 2.5 V might be destructive.
+ * @retval None
+ */
+void HAL_SYSCFG_DisableIOSpeedOptimize(void)
+{
+#if defined(SYSCFG_CCCSR_HSLV)
+ CLEAR_BIT(SYSCFG->CCCSR, SYSCFG_CCCSR_HSLV);
+#else
+ CLEAR_BIT(SYSCFG->CCCSR, (SYSCFG_CCCSR_HSLV0| SYSCFG_CCCSR_HSLV1 | SYSCFG_CCCSR_HSLV2 | SYSCFG_CCCSR_HSLV3));
+#endif /* SYSCFG_CCCSR_HSLV */
+}
+
+/**
+ * @brief Code selection for the I/O Compensation cell
+ * @param SYSCFG_CompCode: Selects the code to be applied for the I/O compensation cell
+ * This parameter can be one of the following values:
+ * @arg SYSCFG_CELL_CODE : Select Code from the cell (available in the SYSCFG_CCVR)
+ * @arg SYSCFG_REGISTER_CODE: Select Code from the SYSCFG compensation cell code register (SYSCFG_CCCR)
+ * @retval None
+ */
+void HAL_SYSCFG_CompensationCodeSelect(uint32_t SYSCFG_CompCode)
+{
+ /* Check the parameter */
+ assert_param(IS_SYSCFG_CODE_SELECT(SYSCFG_CompCode));
+ MODIFY_REG(SYSCFG->CCCSR, SYSCFG_CCCSR_CS, (uint32_t)(SYSCFG_CompCode));
+}
+
+/**
+ * @brief Code selection for the I/O Compensation cell
+ * @param SYSCFG_PMOSCode: PMOS compensation code
+ * This code is applied to the I/O compensation cell when the CS bit of the
+ * SYSCFG_CMPCR is set
+ * @param SYSCFG_NMOSCode: NMOS compensation code
+ * This code is applied to the I/O compensation cell when the CS bit of the
+ * SYSCFG_CMPCR is set
+ * @retval None
+ */
+void HAL_SYSCFG_CompensationCodeConfig(uint32_t SYSCFG_PMOSCode, uint32_t SYSCFG_NMOSCode )
+{
+ /* Check the parameter */
+ assert_param(IS_SYSCFG_CODE_CONFIG(SYSCFG_PMOSCode));
+ assert_param(IS_SYSCFG_CODE_CONFIG(SYSCFG_NMOSCode));
+ MODIFY_REG(SYSCFG->CCCR, SYSCFG_CCCR_NCC|SYSCFG_CCCR_PCC, (((uint32_t)(SYSCFG_PMOSCode)<< 4)|(uint32_t)(SYSCFG_NMOSCode)) );
+}
+
+#if defined(SYSCFG_CCCR_NCC_MMC)
+/**
+ * @brief Code selection for the I/O Compensation cell
+ * @param SYSCFG_PMOSCode: VDDMMC PMOS compensation code
+ * This code is applied to the I/O compensation cell when the CS bit of the
+ * SYSCFG_CMPCR is set
+ * @param SYSCFG_NMOSCode: VDDMMC NMOS compensation code
+ * This code is applied to the I/O compensation cell when the CS bit of the
+ * SYSCFG_CMPCR is set
+ * @retval None
+ */
+void HAL_SYSCFG_VDDMMC_CompensationCodeConfig(uint32_t SYSCFG_PMOSCode, uint32_t SYSCFG_NMOSCode )
+{
+ /* Check the parameter */
+ assert_param(IS_SYSCFG_CODE_CONFIG(SYSCFG_PMOSCode));
+ assert_param(IS_SYSCFG_CODE_CONFIG(SYSCFG_NMOSCode));
+ MODIFY_REG(SYSCFG->CCCR, (SYSCFG_CCCR_NCC_MMC | SYSCFG_CCCR_PCC_MMC), (((uint32_t)(SYSCFG_PMOSCode)<< 4)|(uint32_t)(SYSCFG_NMOSCode)) );
+}
+#endif /* SYSCFG_CCCR_NCC_MMC */
+
+#if defined(SYSCFG_ADC2ALT_ADC2_ROUT0)
+/** @brief SYSCFG ADC2 internal input alternate connection macros
+ * @param Adc2AltRout0 This parameter can be a value of :
+ * @arg @ref SYSCFG_ADC2_ROUT0_DAC1_1 DAC1_out1 connected to ADC2 VINP[16]
+ * @arg @ref SYSCFG_ADC2_ROUT0_VBAT4 VBAT/4 connected to ADC2 VINP[16]
+ */
+void HAL_SYSCFG_ADC2ALT_Rout0Config(uint32_t Adc2AltRout0)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_ADC2ALT_ROUT0(Adc2AltRout0));
+
+ MODIFY_REG(SYSCFG->ADC2ALT, SYSCFG_ADC2ALT_ADC2_ROUT0, Adc2AltRout0);
+}
+#endif /*SYSCFG_ADC2ALT_ADC2_ROUT0*/
+
+#if defined(SYSCFG_ADC2ALT_ADC2_ROUT1)
+/** @brief SYSCFG ADC2 internal input alternate connection macros
+ * @param Adc2AltRout1 This parameter can be a value of :
+ * @arg @ref SYSCFG_ADC2_ROUT1_DAC1_2 DAC1_out2 connected to ADC2 VINP[17]
+ * @arg @ref SYSCFG_ADC2_ROUT1_VREFINT VREFINT connected to ADC2 VINP[17]
+ */
+void HAL_SYSCFG_ADC2ALT_Rout1Config(uint32_t Adc2AltRout1)
+{
+ /* Check the parameters */
+ assert_param(IS_SYSCFG_ADC2ALT_ROUT1(Adc2AltRout1));
+
+ MODIFY_REG(SYSCFG->ADC2ALT, SYSCFG_ADC2ALT_ADC2_ROUT1, Adc2AltRout1);
+}
+#endif /*SYSCFG_ADC2ALT_ADC2_ROUT1*/
+
+/**
+ * @brief Enable the Debug Module during Domain1/CDomain SLEEP mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGSleepMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEPD1);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain1/CDomain SLEEP mode
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGSleepMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEPD1);
+}
+
+
+/**
+ * @brief Enable the Debug Module during Domain1/CDomain STOP mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStopMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD1);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain1/CDomain STOP mode
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGStopMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD1);
+}
+
+/**
+ * @brief Enable the Debug Module during Domain1/CDomain STANDBY mode
+ * @retval None
+ */
+void HAL_DBGMCU_EnableDBGStandbyMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD1);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain1/CDomain STANDBY mode
+ * @retval None
+ */
+void HAL_DBGMCU_DisableDBGStandbyMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD1);
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Enable the Debug Module during Domain1 SLEEP mode
+ * @retval None
+ */
+void HAL_EnableDomain2DBGSleepMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEPD2);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain2 SLEEP mode
+ * @retval None
+ */
+void HAL_DisableDomain2DBGSleepMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEPD2);
+}
+
+/**
+ * @brief Enable the Debug Module during Domain2 STOP mode
+ * @retval None
+ */
+void HAL_EnableDomain2DBGStopMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD2);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain2 STOP mode
+ * @retval None
+ */
+void HAL_DisableDomain2DBGStopMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD2);
+}
+
+/**
+ * @brief Enable the Debug Module during Domain2 STANDBY mode
+ * @retval None
+ */
+void HAL_EnableDomain2DBGStandbyMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD2);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain2 STANDBY mode
+ * @retval None
+ */
+void HAL_DisableDomain2DBGStandbyMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD2);
+}
+#endif /*DUAL_CORE*/
+
+#if defined(DBGMCU_CR_DBG_STOPD3)
+/**
+ * @brief Enable the Debug Module during Domain3/SRDomain STOP mode
+ * @retval None
+ */
+void HAL_EnableDomain3DBGStopMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD3);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain3/SRDomain STOP mode
+ * @retval None
+ */
+void HAL_DisableDomain3DBGStopMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOPD3);
+}
+#endif /*DBGMCU_CR_DBG_STOPD3*/
+
+#if defined(DBGMCU_CR_DBG_STANDBYD3)
+/**
+ * @brief Enable the Debug Module during Domain3/SRDomain STANDBY mode
+ * @retval None
+ */
+void HAL_EnableDomain3DBGStandbyMode(void)
+{
+ SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD3);
+}
+
+/**
+ * @brief Disable the Debug Module during Domain3/SRDomain STANDBY mode
+ * @retval None
+ */
+void HAL_DisableDomain3DBGStandbyMode(void)
+{
+ CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBYD3);
+}
+#endif /*DBGMCU_CR_DBG_STANDBYD3*/
+
+/**
+ * @brief Set the FMC Memory Mapping Swapping config.
+ * @param BankMapConfig: Defines the FMC Bank mapping configuration. This parameter can be
+ FMC_SWAPBMAP_DISABLE, FMC_SWAPBMAP_SDRAM_SRAM, FMC_SWAPBMAP_SDRAMB2
+ * @retval HAL state
+ */
+void HAL_SetFMCMemorySwappingConfig(uint32_t BankMapConfig)
+{
+ /* Check the parameter */
+ assert_param(IS_FMC_SWAPBMAP_MODE(BankMapConfig));
+ MODIFY_REG(FMC_Bank1_R->BTCR[0], FMC_BCR1_BMAP, BankMapConfig);
+}
+
+/**
+ * @brief Get FMC Bank mapping mode.
+ * @retval The FMC Bank mapping mode. This parameter can be
+ FMC_SWAPBMAP_DISABLE, FMC_SWAPBMAP_SDRAM_SRAM, FMC_SWAPBMAP_SDRAMB2
+*/
+uint32_t HAL_GetFMCMemorySwappingConfig(void)
+{
+ return READ_BIT(FMC_Bank1_R->BTCR[0], FMC_BCR1_BMAP);
+}
+
+/**
+ * @brief Configure the EXTI input event line edge
+ * @note No edge configuration for direct lines but for configurable lines:(EXTI_LINE0..EXTI_LINE21),
+ * EXTI_LINE49,EXTI_LINE51,EXTI_LINE82,EXTI_LINE84,EXTI_LINE85 and EXTI_LINE86.
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0....EXTI_LINE87)excluding :line45, line81,line83 which are reserved
+ * @param EXTI_Edge: Specifies EXTI line Edge used.
+ * This parameter can be one of the following values :
+ * @arg EXTI_RISING_EDGE : Configurable line, with Rising edge trigger detection
+ * @arg EXTI_FALLING_EDGE: Configurable line, with Falling edge trigger detection
+ * @retval None
+ */
+void HAL_EXTI_EdgeConfig(uint32_t EXTI_Line , uint32_t EXTI_Edge )
+{
+ /* Check the parameter */
+ assert_param(IS_HAL_EXTI_CONFIG_LINE(EXTI_Line));
+ assert_param(IS_EXTI_EDGE_LINE(EXTI_Edge));
+
+ /* Clear Rising Falling edge configuration */
+ CLEAR_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI->FTSR1)) + ((EXTI_Line >> 5 ) * 0x20UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ CLEAR_BIT( *(__IO uint32_t *) (((uint32_t) &(EXTI->RTSR1)) + ((EXTI_Line >> 5 ) * 0x20UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+
+ if( (EXTI_Edge & EXTI_RISING_EDGE) == EXTI_RISING_EDGE)
+ {
+ SET_BIT( *(__IO uint32_t *) (((uint32_t) &(EXTI->RTSR1)) + ((EXTI_Line >> 5 ) * 0x20UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ if( (EXTI_Edge & EXTI_FALLING_EDGE) == EXTI_FALLING_EDGE)
+ {
+ SET_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI->FTSR1)) + ((EXTI_Line >> 5 ) * 0x20UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+}
+
+/**
+ * @brief Generates a Software interrupt on selected EXTI line.
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0..EXTI_LINE21),EXTI_LINE49,EXTI_LINE51,EXTI_LINE82,EXTI_LINE84,EXTI_LINE85 and EXTI_LINE86.
+ * @retval None
+ */
+void HAL_EXTI_GenerateSWInterrupt(uint32_t EXTI_Line)
+{
+ /* Check the parameters */
+ assert_param(IS_HAL_EXTI_CONFIG_LINE(EXTI_Line));
+
+ SET_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI->SWIER1)) + ((EXTI_Line >> 5 ) * 0x20UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+}
+
+
+/**
+ * @brief Clears the EXTI's line pending flags for Domain D1
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0....EXTI_LINE87)excluding :line45, line81,line83 which are reserved
+ * @retval None
+ */
+void HAL_EXTI_D1_ClearFlag(uint32_t EXTI_Line)
+{
+ /* Check the parameters */
+ assert_param(IS_EXTI_D1_LINE(EXTI_Line));
+ WRITE_REG(*(__IO uint32_t *) (((uint32_t) &(EXTI_D1->PR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Clears the EXTI's line pending flags for Domain D2
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0....EXTI_LINE87)excluding :line45, line81,line83 which are reserved
+ * @retval None
+ */
+void HAL_EXTI_D2_ClearFlag(uint32_t EXTI_Line)
+{
+ /* Check the parameters */
+ assert_param(IS_EXTI_D2_LINE(EXTI_Line));
+ WRITE_REG(*(__IO uint32_t *) (((uint32_t) &(EXTI_D2->PR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+}
+
+#endif /*DUAL_CORE*/
+/**
+ * @brief Configure the EXTI input event line for Domain D1
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0....EXTI_LINE87)excluding :line45, line81,line83 which are reserved
+ * @param EXTI_Mode: Specifies which EXTI line is used as interrupt or an event.
+ * This parameter can be one or a combination of the following values :
+ * @arg EXTI_MODE_IT : Interrupt Mode selected
+ * @arg EXTI_MODE_EVT : Event Mode selected
+ * @param EXTI_LineCmd controls (Enable/Disable) the EXTI line.
+
+ * @retval None
+ */
+void HAL_EXTI_D1_EventInputConfig(uint32_t EXTI_Line , uint32_t EXTI_Mode, uint32_t EXTI_LineCmd )
+{
+ /* Check the parameter */
+ assert_param(IS_EXTI_D1_LINE(EXTI_Line));
+ assert_param(IS_EXTI_MODE_LINE(EXTI_Mode));
+
+ if( (EXTI_Mode & EXTI_MODE_IT) == EXTI_MODE_IT)
+ {
+ if( EXTI_LineCmd == 0UL)
+ {
+ /* Clear EXTI line configuration */
+ CLEAR_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI_D1->IMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)),(uint32_t)(1UL << (EXTI_Line & 0x1FUL)) );
+ }
+ else
+ {
+ SET_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI_D1->IMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ }
+
+ if( (EXTI_Mode & EXTI_MODE_EVT) == EXTI_MODE_EVT)
+ {
+ if( EXTI_LineCmd == 0UL)
+ {
+ /* Clear EXTI line configuration */
+ CLEAR_BIT( *(__IO uint32_t *) (((uint32_t) &(EXTI_D1->EMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ else
+ {
+ SET_BIT( *(__IO uint32_t *) (((uint32_t) &(EXTI_D1->EMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ }
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Configure the EXTI input event line for Domain D2
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0....EXTI_LINE87)excluding :line45, line81,line83 which are reserved
+ * @param EXTI_Mode: Specifies which EXTI line is used as interrupt or an event.
+ * This parameter can be one or a combination of the following values :
+ * @arg EXTI_MODE_IT : Interrupt Mode selected
+ * @arg EXTI_MODE_EVT : Event Mode selected
+ * @param EXTI_LineCmd controls (Enable/Disable) the EXTI line.
+
+ * @retval None
+ */
+void HAL_EXTI_D2_EventInputConfig(uint32_t EXTI_Line , uint32_t EXTI_Mode, uint32_t EXTI_LineCmd )
+{
+ /* Check the parameter */
+ assert_param(IS_EXTI_D2_LINE(EXTI_Line));
+ assert_param(IS_EXTI_MODE_LINE(EXTI_Mode));
+
+ if( (EXTI_Mode & EXTI_MODE_IT) == EXTI_MODE_IT)
+ {
+ if( EXTI_LineCmd == 0UL)
+ {
+ /* Clear EXTI line configuration */
+ CLEAR_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI_D2->IMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)),(uint32_t)(1UL << (EXTI_Line & 0x1FUL)) );
+ }
+ else
+ {
+ SET_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI_D2->IMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ }
+
+ if( (EXTI_Mode & EXTI_MODE_EVT) == EXTI_MODE_EVT)
+ {
+ if( EXTI_LineCmd == 0UL)
+ {
+ /* Clear EXTI line configuration */
+ CLEAR_BIT( *(__IO uint32_t *) (((uint32_t) &(EXTI_D2->EMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ else
+ {
+ SET_BIT( *(__IO uint32_t *) (((uint32_t) &(EXTI_D2->EMR1)) + ((EXTI_Line >> 5 ) * 0x10UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+ }
+}
+#endif /*DUAL_CORE*/
+
+/**
+ * @brief Configure the EXTI input event line for Domain D3
+ * @param EXTI_Line: Specifies the EXTI LINE, it can be one of the following values,
+ * (EXTI_LINE0...EXTI_LINE15),(EXTI_LINE19...EXTI_LINE21),EXTI_LINE25, EXTI_LINE34,
+ * EXTI_LINE35,EXTI_LINE41,(EXTI_LINE48...EXTI_LINE53)
+ * @param EXTI_LineCmd controls (Enable/Disable) the EXTI line.
+ * @param EXTI_ClearSrc: Specifies the clear source of D3 pending event.
+ * This parameter can be one of the following values :
+ * @arg BDMA_CH6_CLEAR : BDMA ch6 event selected as D3 domain pendclear source
+ * @arg BDMA_CH7_CLEAR : BDMA ch7 event selected as D3 domain pendclear source
+ * @arg LPTIM4_OUT_CLEAR : LPTIM4 out selected as D3 domain pendclear source
+ * @arg LPTIM5_OUT_CLEAR : LPTIM5 out selected as D3 domain pendclear source
+ * @retval None
+ */
+void HAL_EXTI_D3_EventInputConfig(uint32_t EXTI_Line, uint32_t EXTI_LineCmd , uint32_t EXTI_ClearSrc )
+{
+ __IO uint32_t *pRegv;
+
+ /* Check the parameter */
+ assert_param(IS_EXTI_D3_LINE(EXTI_Line));
+ assert_param(IS_EXTI_D3_CLEAR(EXTI_ClearSrc));
+
+ if( EXTI_LineCmd == 0UL)
+ {
+ /* Clear EXTI line configuration */
+ CLEAR_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI->D3PMR1)) + ((EXTI_Line >> 5 ) * 0x20UL)),(uint32_t)(1UL << (EXTI_Line & 0x1FUL)) );
+ }
+ else
+ {
+ SET_BIT(*(__IO uint32_t *) (((uint32_t) &(EXTI->D3PMR1)) +((EXTI_Line >> 5 ) * 0x20UL)), (uint32_t)(1UL << (EXTI_Line & 0x1FUL)));
+ }
+
+ if(((EXTI_Line>>4)%2UL) == 0UL)
+ {
+ pRegv = (__IO uint32_t *) (((uint32_t) &(EXTI->D3PCR1L)) + ((EXTI_Line >> 5 ) * 0x20UL));
+ }
+ else
+ {
+ pRegv = (__IO uint32_t *) (((uint32_t) &(EXTI->D3PCR1H)) + ((EXTI_Line >> 5 ) * 0x20UL));
+ }
+ MODIFY_REG(*pRegv, (uint32_t)(3UL << ((EXTI_Line*2UL) & 0x1FUL)), (uint32_t)(EXTI_ClearSrc << ((EXTI_Line*2UL) & 0x1FUL)));
+
+}
+
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c
new file mode 100755
index 0000000..5c158d5
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_cortex.c
@@ -0,0 +1,558 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_cortex.c
+ * @author MCD Application Team
+ * @brief CORTEX HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the CORTEX:
+ * + Initialization and 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-M 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_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
+ HAL_SYSTICK_Config() function call. The HAL_SYSTICK_CLKSourceConfig() macro is defined
+ inside the stm32h7xx_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
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file in
+ * the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_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 (stm32h7xxxx.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;
+
+ /* 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 (stm32h7xxxx.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 (stm32h7xxxx.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 Disables the MPU
+ * @retval None
+ */
+void HAL_MPU_Disable(void)
+{
+ /* Make sure outstanding transfers are done */
+ __DMB();
+
+ /* Disable fault exceptions */
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+
+ /* Disable the MPU and clear the control register*/
+ MPU->CTRL = 0;
+}
+
+/**
+ * @brief Enables the MPU
+ * @param MPU_Control Specifies the control mode of the MPU during hard fault,
+ * NMI, FAULTMASK and privileged access to the default memory
+ * This parameter can be one of the following values:
+ * @arg MPU_HFNMI_PRIVDEF_NONE
+ * @arg MPU_HARDFAULT_NMI
+ * @arg MPU_PRIVILEGED_DEFAULT
+ * @arg MPU_HFNMI_PRIVDEF
+ * @retval None
+ */
+void HAL_MPU_Enable(uint32_t MPU_Control)
+{
+ /* Enable the MPU */
+ MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+
+ /* Enable fault exceptions */
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+
+ /* Ensure MPU setting take effects */
+ __DSB();
+ __ISB();
+}
+
+/**
+ * @brief Enables the MPU Region.
+ * @retval None
+ */
+void HAL_MPU_EnableRegion(uint32_t RegionNumber)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(RegionNumber));
+
+ /* Set the Region number */
+ MPU->RNR = RegionNumber;
+
+ /* Enable the Region */
+ SET_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
+}
+
+/**
+ * @brief Disables the MPU Region.
+ * @retval None
+ */
+void HAL_MPU_DisableRegion(uint32_t RegionNumber)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(RegionNumber));
+
+ /* Set the Region number */
+ MPU->RNR = RegionNumber;
+
+ /* Disable the Region */
+ CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
+}
+
+/**
+ * @brief 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(const MPU_Region_InitTypeDef *MPU_Init)
+{
+ /* Check the parameters */
+ assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));
+ assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));
+ assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));
+ assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));
+ assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));
+ assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));
+ assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));
+ assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));
+ assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));
+ assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));
+
+ /* Set the Region number */
+ MPU->RNR = MPU_Init->Number;
+
+ /* Disable the Region */
+ CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
+
+ /* Apply configuration */
+ MPU->RBAR = MPU_Init->BaseAddress;
+ MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) |
+ ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) |
+ ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) |
+ ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) |
+ ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) |
+ ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) |
+ ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) |
+ ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) |
+ ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos);
+}
+#endif /* __MPU_PRESENT */
+
+/**
+ * @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 (stm32h7xxxx.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 (stm32h7xxxx.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 (stm32h7xxxx.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 (stm32h7xxxx.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 (stm32h7xxxx.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
+ */
+}
+
+#if defined(DUAL_CORE)
+
+/**
+ * @brief Returns the current CPU ID.
+ * @retval CPU identifier
+ */
+uint32_t HAL_GetCurrentCPUID(void)
+{
+ if (((SCB->CPUID & 0x000000F0U) >> 4 )== 0x7U)
+ {
+ return CM7_CPUID;
+ }
+ else
+ {
+ return CM4_CPUID;
+ }
+}
+
+#else
+
+/**
+* @brief Returns the current CPU ID.
+* @retval CPU identifier
+*/
+uint32_t HAL_GetCurrentCPUID(void)
+{
+ return CM7_CPUID;
+}
+
+#endif /*DUAL_CORE*/
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c
new file mode 100755
index 0000000..0b32d9c
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma.c
@@ -0,0 +1,2059 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dma.c
+ * @author MCD Application Team
+ * @brief DMA HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Direct Memory Access (DMA) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and errors functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Enable and configure the peripheral to be connected to the DMA 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_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
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMA DMA
+ * @brief DMA HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/** @addtogroup DMA_Private_Types
+ * @{
+ */
+typedef struct
+{
+ __IO uint32_t ISR; /*!< DMA interrupt status register */
+ __IO uint32_t Reserved0;
+ __IO uint32_t IFCR; /*!< DMA interrupt flag clear register */
+} DMA_Base_Registers;
+
+typedef struct
+{
+ __IO uint32_t ISR; /*!< BDMA interrupt status register */
+ __IO uint32_t IFCR; /*!< BDMA interrupt flag clear register */
+} BDMA_Base_Registers;
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup DMA_Private_Constants
+ * @{
+ */
+#define HAL_TIMEOUT_DMA_ABORT (5U) /* 5 ms */
+
+#define BDMA_PERIPH_TO_MEMORY (0x00000000U) /*!< Peripheral to memory direction */
+#define BDMA_MEMORY_TO_PERIPH ((uint32_t)BDMA_CCR_DIR) /*!< Memory to peripheral direction */
+#define BDMA_MEMORY_TO_MEMORY ((uint32_t)BDMA_CCR_MEM2MEM) /*!< Memory to memory direction */
+
+/* DMA to BDMA conversion */
+#define DMA_TO_BDMA_DIRECTION(__DMA_DIRECTION__) (((__DMA_DIRECTION__) == DMA_MEMORY_TO_PERIPH)? BDMA_MEMORY_TO_PERIPH: \
+ ((__DMA_DIRECTION__) == DMA_MEMORY_TO_MEMORY)? BDMA_MEMORY_TO_MEMORY: \
+ BDMA_PERIPH_TO_MEMORY)
+
+#define DMA_TO_BDMA_PERIPHERAL_INC(__DMA_PERIPHERAL_INC__) ((__DMA_PERIPHERAL_INC__) >> 3U)
+#define DMA_TO_BDMA_MEMORY_INC(__DMA_MEMORY_INC__) ((__DMA_MEMORY_INC__) >> 3U)
+
+#define DMA_TO_BDMA_PDATA_SIZE(__DMA_PDATA_SIZE__) ((__DMA_PDATA_SIZE__) >> 3U)
+#define DMA_TO_BDMA_MDATA_SIZE(__DMA_MDATA_SIZE__) ((__DMA_MDATA_SIZE__) >> 3U)
+
+#define DMA_TO_BDMA_MODE(__DMA_MODE__) ((__DMA_MODE__) >> 3U)
+
+#define DMA_TO_BDMA_PRIORITY(__DMA_PRIORITY__) ((__DMA_PRIORITY__) >> 4U)
+
+#if defined(UART9)
+#define IS_DMA_UART_USART_REQUEST(__REQUEST__) ((((__REQUEST__) >= DMA_REQUEST_USART1_RX) && ((__REQUEST__) <= DMA_REQUEST_USART3_TX)) || \
+ (((__REQUEST__) >= DMA_REQUEST_UART4_RX) && ((__REQUEST__) <= DMA_REQUEST_UART5_TX )) || \
+ (((__REQUEST__) >= DMA_REQUEST_USART6_RX) && ((__REQUEST__) <= DMA_REQUEST_USART6_TX)) || \
+ (((__REQUEST__) >= DMA_REQUEST_UART7_RX) && ((__REQUEST__) <= DMA_REQUEST_UART8_TX )) || \
+ (((__REQUEST__) >= DMA_REQUEST_UART9_RX) && ((__REQUEST__) <= DMA_REQUEST_USART10_TX )))
+#else
+#define IS_DMA_UART_USART_REQUEST(__REQUEST__) ((((__REQUEST__) >= DMA_REQUEST_USART1_RX) && ((__REQUEST__) <= DMA_REQUEST_USART3_TX)) || \
+ (((__REQUEST__) >= DMA_REQUEST_UART4_RX) && ((__REQUEST__) <= DMA_REQUEST_UART5_TX )) || \
+ (((__REQUEST__) >= DMA_REQUEST_USART6_RX) && ((__REQUEST__) <= DMA_REQUEST_USART6_TX)) || \
+ (((__REQUEST__) >= DMA_REQUEST_UART7_RX) && ((__REQUEST__) <= DMA_REQUEST_UART8_TX )))
+
+#endif
+/**
+ * @}
+ */
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup DMA_Private_Functions
+ * @{
+ */
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
+static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef DMA_CheckFifoParam(const DMA_HandleTypeDef *hdma);
+static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
+static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
+
+/**
+ * @}
+ */
+
+/* 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 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.
+ The HAL_DMA_DeInit function allows to deinitialize the DMA stream.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize 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 registerValue;
+ uint32_t tickstart = HAL_GetTick();
+ DMA_Base_Registers *regs_dma;
+ BDMA_Base_Registers *regs_bdma;
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+ assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
+ assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
+ assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
+ assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
+ assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
+ assert_param(IS_DMA_MODE(hdma->Init.Mode));
+ assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ assert_param(IS_DMA_REQUEST(hdma->Init.Request));
+ 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;
+
+ /* Allocate lock resource */
+ __HAL_UNLOCK(hdma);
+
+ /* Disable the peripheral */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Check if the DMA Stream is effectively disabled */
+ while((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
+ {
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Get the CR register value */
+ registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->CR;
+
+ /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
+ registerValue &= ((uint32_t)~(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 */
+ registerValue |= 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 */
+ registerValue |= hdma->Init.MemBurst | hdma->Init.PeriphBurst;
+ }
+
+ /* Work around for Errata 2.22: UART/USART- DMA transfer lock: DMA stream could be
+ lock when transferring data to/from USART/UART */
+#if (STM32H7_DEV_ID == 0x450UL)
+ if(((DBGMCU->IDCODE & 0xFFFF0000U) >= 0x20000000U) && (IS_DMA_UART_USART_REQUEST(hdma->Init.Request) != 0U))
+#else
+ if(IS_DMA_UART_USART_REQUEST(hdma->Init.Request) != 0U)
+#endif /* STM32H7_DEV_ID == 0x450UL */
+ {
+ registerValue |= DMA_SxCR_TRBUFF;
+ }
+
+ /* Write to DMA Stream CR register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR = registerValue;
+
+ /* Get the FCR register value */
+ registerValue = ((DMA_Stream_TypeDef *)hdma->Instance)->FCR;
+
+ /* Clear Direct mode and FIFO threshold bits */
+ registerValue &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
+
+ /* Prepare the DMA Stream FIFO configuration */
+ registerValue |= 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 */
+ registerValue |= hdma->Init.FIFOThreshold;
+
+ /* Check compatibility between FIFO threshold level and size of the memory burst */
+ /* for INCR4, INCR8, INCR16 */
+ if(hdma->Init.MemBurst != DMA_MBURST_SINGLE)
+ {
+ if (DMA_CheckFifoParam(hdma) != HAL_OK)
+ {
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Write to DMA Stream FCR */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = registerValue;
+
+ /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
+ DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
+ regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
+
+ /* Clear all interrupt flags */
+ regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+ }
+ else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
+ {
+ if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U)
+ {
+ /* Check the request parameter */
+ assert_param(IS_BDMA_REQUEST(hdma->Init.Request));
+ }
+
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Allocate lock resource */
+ __HAL_UNLOCK(hdma);
+
+ /* Get the CR register value */
+ registerValue = ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR;
+
+ /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, MEM2MEM, DBM and CT bits */
+ registerValue &= ((uint32_t)~(BDMA_CCR_PL | BDMA_CCR_MSIZE | BDMA_CCR_PSIZE | \
+ BDMA_CCR_MINC | BDMA_CCR_PINC | BDMA_CCR_CIRC | \
+ BDMA_CCR_DIR | BDMA_CCR_MEM2MEM | BDMA_CCR_DBM | \
+ BDMA_CCR_CT));
+
+ /* Prepare the DMA Channel configuration */
+ registerValue |= DMA_TO_BDMA_DIRECTION(hdma->Init.Direction) |
+ DMA_TO_BDMA_PERIPHERAL_INC(hdma->Init.PeriphInc) |
+ DMA_TO_BDMA_MEMORY_INC(hdma->Init.MemInc) |
+ DMA_TO_BDMA_PDATA_SIZE(hdma->Init.PeriphDataAlignment) |
+ DMA_TO_BDMA_MDATA_SIZE(hdma->Init.MemDataAlignment) |
+ DMA_TO_BDMA_MODE(hdma->Init.Mode) |
+ DMA_TO_BDMA_PRIORITY(hdma->Init.Priority);
+
+ /* Write to DMA Channel CR register */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR = registerValue;
+
+ /* calculation of the channel index */
+ hdma->StreamIndex = (((uint32_t)((uint32_t*)hdma->Instance) - (uint32_t)BDMA_Channel0) / ((uint32_t)BDMA_Channel1 - (uint32_t)BDMA_Channel0)) << 2U;
+
+ /* Initialize StreamBaseAddress and StreamIndex parameters to be used to calculate
+ DMA steam Base Address needed by HAL_DMA_IRQHandler() and HAL_DMA_PollForTransfer() */
+ regs_bdma = (BDMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
+
+ /* Clear all interrupt flags */
+ regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
+ }
+ else
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
+ hdma->State = HAL_DMA_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Initialize parameters for DMAMUX channel :
+ DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
+ */
+ DMA_CalcDMAMUXChannelBaseAndMask(hdma);
+
+ if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
+ {
+ /* if memory to memory force the request to 0*/
+ hdma->Init.Request = DMA_REQUEST_MEM2MEM;
+ }
+
+ /* Set peripheral request to DMAMUX channel */
+ hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ /* Initialize parameters for DMAMUX request generator :
+ if the DMA request is DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR7
+ */
+ if((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
+ {
+ /* Initialize parameters for DMAMUX request generator :
+ DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
+ DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
+
+ /* Reset the DMAMUX request generator register */
+ hdma->DMAmuxRequestGen->RGCR = 0U;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ else
+ {
+ hdma->DMAmuxRequestGen = 0U;
+ hdma->DMAmuxRequestGenStatus = 0U;
+ hdma->DMAmuxRequestGenStatusMask = 0U;
+ }
+ }
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ 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)
+{
+ DMA_Base_Registers *regs_dma;
+ BDMA_Base_Registers *regs_bdma;
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the selected DMA Streamx */
+ __HAL_DMA_DISABLE(hdma);
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Reset DMA Streamx control register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR = 0U;
+
+ /* Reset DMA Streamx number of data to transfer register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = 0U;
+
+ /* Reset DMA Streamx peripheral address register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = 0U;
+
+ /* Reset DMA Streamx memory 0 address register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = 0U;
+
+ /* Reset DMA Streamx memory 1 address register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = 0U;
+
+ /* Reset DMA Streamx FIFO control register */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->FCR = (uint32_t)0x00000021U;
+
+ /* Get DMA steam Base Address */
+ regs_dma = (DMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
+
+ /* Clear all interrupt flags at correct offset within the register */
+ regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+ }
+ else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
+ {
+ /* Reset DMA Channel control register */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR = 0U;
+
+ /* Reset DMA Channel Number of Data to Transfer register */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = 0U;
+
+ /* Reset DMA Channel peripheral address register */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = 0U;
+
+ /* Reset DMA Channel memory 0 address register */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = 0U;
+
+ /* Reset DMA Channel memory 1 address register */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM1AR = 0U;
+
+ /* Get DMA steam Base Address */
+ regs_bdma = (BDMA_Base_Registers *)DMA_CalcBaseAndBitshift(hdma);
+
+ /* Clear all interrupt flags at correct offset within the register */
+ regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
+ }
+ else
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+#if defined (BDMA1) /* No DMAMUX available for BDMA1 available on STM32H7Ax/Bx devices only */
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+#endif /* BDMA1 */
+ {
+ /* Initialize parameters for DMAMUX channel :
+ DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
+ DMA_CalcDMAMUXChannelBaseAndMask(hdma);
+
+ if(hdma->DMAmuxChannel != 0U)
+ {
+ /* Resett he DMAMUX channel that corresponds to the DMA stream */
+ hdma->DMAmuxChannel->CCR = 0U;
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+ }
+
+ if((hdma->Init.Request >= DMA_REQUEST_GENERATOR0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR7))
+ {
+ /* Initialize parameters for DMAMUX request generator :
+ DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask */
+ DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
+
+ /* Reset the DMAMUX request generator register */
+ hdma->DMAmuxRequestGen->RGCR = 0U;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+
+ hdma->DMAmuxRequestGen = 0U;
+ hdma->DMAmuxRequestGenStatus = 0U;
+ hdma->DMAmuxRequestGenStatusMask = 0U;
+ }
+
+
+ /* Clean callbacks */
+ hdma->XferCpltCallback = NULL;
+ hdma->XferHalfCpltCallback = NULL;
+ hdma->XferM1CpltCallback = NULL;
+ hdma->XferM1HalfCpltCallback = NULL;
+ hdma->XferErrorCallback = NULL;
+ hdma->XferAbortCallback = NULL;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Initialize the DMA state */
+ hdma->State = HAL_DMA_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @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
+ (+) Register and Unregister DMA callbacks
+ (+) 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)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if(HAL_DMA_STATE_READY == hdma->State)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* 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);
+ }
+ else
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Start the DMA Transfer with interrupt enabled.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA 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)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if(HAL_DMA_STATE_READY == hdma->State)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ /* Disable the peripheral */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Configure the source, destination address and the data length */
+ DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Enable Common interrupts*/
+ MODIFY_REG(((DMA_Stream_TypeDef *)hdma->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
+
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Enable Half Transfer IT if corresponding Callback is set */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR |= DMA_IT_HT;
+ }
+ }
+ else /* BDMA channel */
+ {
+ /* Enable Common interrupts */
+ MODIFY_REG(((BDMA_Channel_TypeDef *)hdma->Instance)->CCR, (BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE), (BDMA_CCR_TCIE | BDMA_CCR_TEIE));
+
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /*Enable Half Transfer IT if corresponding Callback is set */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR |= BDMA_CCR_HTIE;
+ }
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Check if DMAMUX Synchronization is enabled */
+ if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
+ {
+ /* Enable DMAMUX sync overrun IT*/
+ hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
+ }
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
+ /* enable the request gen overrun IT */
+ hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
+ }
+ }
+
+ /* Enable the Peripheral */
+ __HAL_DMA_ENABLE(hdma);
+ }
+ else
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @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)
+{
+ /* calculate DMA base and stream number */
+ DMA_Base_Registers *regs_dma;
+ BDMA_Base_Registers *regs_bdma;
+ const __IO uint32_t *enableRegister;
+
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the DMA peripheral state */
+ if(hdma->State != HAL_DMA_STATE_BUSY)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Disable the stream/channel */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Disable all the transfer interrupts */
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Disable DMA All Interrupts */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT);
+ ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
+
+ enableRegister = (__IO uint32_t *)(&(((DMA_Stream_TypeDef *)hdma->Instance)->CR));
+ }
+ else /* BDMA channel */
+ {
+ /* Disable DMA All Interrupts */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE);
+
+ enableRegister = (__IO uint32_t *)(&(((BDMA_Channel_TypeDef *)hdma->Instance)->CCR));
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* disable the DMAMUX sync overrun IT */
+ hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
+ }
+
+ /* Check if the DMA Stream is effectively disabled */
+ while(((*enableRegister) & DMA_SxCR_EN) != 0U)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
+ {
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_ERROR;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Clear all interrupt flags at correct offset within the register */
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
+ regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+ }
+ else /* BDMA channel */
+ {
+ regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
+ regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT */
+ /* disable the request gen overrun IT */
+ hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ }
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Aborts the DMA Transfer in Interrupt mode.
+ * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
+{
+ BDMA_Base_Registers *regs_bdma;
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(hdma->State != HAL_DMA_STATE_BUSY)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
+ return HAL_ERROR;
+ }
+ else
+ {
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Set Abort State */
+ hdma->State = HAL_DMA_STATE_ABORT;
+
+ /* Disable the stream */
+ __HAL_DMA_DISABLE(hdma);
+ }
+ else /* BDMA channel */
+ {
+ /* Disable the channel */
+ __HAL_DMA_DISABLE(hdma);
+
+ /* Disable DMA All Interrupts */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR &= ~(BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE);
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* disable the DMAMUX sync overrun IT */
+ hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
+
+ /* Clear all flags */
+ regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
+ regs_bdma->IFCR = ((BDMA_IFCR_CGIF0) << (hdma->StreamIndex & 0x1FU));
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
+ /* disable the request gen overrun IT */
+ hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ }
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ /* Call User Abort callback */
+ if(hdma->XferAbortCallback != NULL)
+ {
+ hdma->XferAbortCallback(hdma);
+ }
+ }
+ }
+
+ return 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.
+ * @note The polling mode is kept in this version for legacy. it is recommended to use the IT model instead.
+ * This model could be used for debug purpose.
+ * @note The HAL_DMA_PollForTransfer API cannot be used in circular and double buffering mode (automatic circular mode).
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t cpltlevel_mask;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* IT status register */
+ __IO uint32_t *isr_reg;
+ /* IT clear flag register */
+ __IO uint32_t *ifcr_reg;
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(HAL_DMA_STATE_BUSY != hdma->State)
+ {
+ /* No transfer ongoing */
+ hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Polling mode not supported in circular mode and double buffering mode */
+ if ((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) != 0U)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
+ return HAL_ERROR;
+ }
+
+ /* Get the level transfer complete flag */
+ if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
+ {
+ /* Transfer Complete flag */
+ cpltlevel_mask = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
+ }
+ else
+ {
+ /* Half Transfer Complete flag */
+ cpltlevel_mask = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
+ }
+
+ isr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->ISR);
+ ifcr_reg = &(((DMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR);
+ }
+ else /* BDMA channel */
+ {
+ /* Polling mode not supported in circular mode */
+ if ((((BDMA_Channel_TypeDef *)hdma->Instance)->CCR & BDMA_CCR_CIRC) != 0U)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
+ return HAL_ERROR;
+ }
+
+ /* Get the level transfer complete flag */
+ if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
+ {
+ /* Transfer Complete flag */
+ cpltlevel_mask = BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU);
+ }
+ else
+ {
+ /* Half Transfer Complete flag */
+ cpltlevel_mask = BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU);
+ }
+
+ isr_reg = &(((BDMA_Base_Registers *)hdma->StreamBaseAddress)->ISR);
+ ifcr_reg = &(((BDMA_Base_Registers *)hdma->StreamBaseAddress)->IFCR);
+ }
+
+ while(((*isr_reg) & cpltlevel_mask) == 0U)
+ {
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ if(((*isr_reg) & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_FE;
+
+ /* Clear the FIFO error flag */
+ (*ifcr_reg) = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
+ }
+
+ if(((*isr_reg) & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_DME;
+
+ /* Clear the Direct Mode error flag */
+ (*ifcr_reg) = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
+ }
+
+ if(((*isr_reg) & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_TE;
+
+ /* Clear the transfer error flag */
+ (*ifcr_reg) = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ }
+ else /* BDMA channel */
+ {
+ if(((*isr_reg) & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ /* When a DMA transfer error occurs */
+ /* A hardware clear of its EN bits is performed */
+ /* Clear all flags */
+ (*isr_reg) = ((BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU));
+
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TE;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Check for the Timeout (Not applicable in circular mode)*/
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U))
+ {
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
+
+ /* if timeout then abort the current transfer */
+ /* No need to check return value: as in this case we will return HAL_ERROR with HAL_DMA_ERROR_TIMEOUT error code */
+ (void) HAL_DMA_Abort(hdma);
+ /*
+ Note that the Abort function will
+ - Clear the transfer error flags
+ - Unlock
+ - Set the State
+ */
+
+ return HAL_ERROR;
+ }
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Check for DMAMUX Request generator (if used) overrun status */
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator Check for DMAMUX request generator overrun */
+ if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
+ {
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
+ }
+ }
+
+ /* Check for DMAMUX Synchronization overrun */
+ if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
+ {
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
+ }
+ }
+ }
+
+
+ /* Get the level transfer complete flag */
+ if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
+ {
+ /* Clear the half transfer and transfer complete flags */
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ (*ifcr_reg) = (DMA_FLAG_HTIF0_4 | DMA_FLAG_TCIF0_4) << (hdma->StreamIndex & 0x1FU);
+ }
+ else /* BDMA channel */
+ {
+ (*ifcr_reg) = (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU));
+ }
+
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+ else /*CompleteLevel = HAL_DMA_HALF_TRANSFER*/
+ {
+ /* Clear the half transfer and transfer complete flags */
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ (*ifcr_reg) = (DMA_FLAG_HTIF0_4) << (hdma->StreamIndex & 0x1FU);
+ }
+ else /* BDMA channel */
+ {
+ (*ifcr_reg) = (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU));
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @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)
+{
+ uint32_t tmpisr_dma, tmpisr_bdma;
+ uint32_t ccr_reg;
+ __IO uint32_t count = 0U;
+ uint32_t timeout = SystemCoreClock / 9600U;
+
+ /* calculate DMA base and stream number */
+ DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
+ BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
+
+ tmpisr_dma = regs_dma->ISR;
+ tmpisr_bdma = regs_bdma->ISR;
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Transfer Error Interrupt management ***************************************/
+ if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U)
+ {
+ /* Disable the transfer error interrupt */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TE);
+
+ /* Clear the transfer error flag */
+ regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_TE;
+ }
+ }
+ /* FIFO Error Interrupt management ******************************************/
+ if ((tmpisr_dma & (DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != 0U)
+ {
+ /* Clear the FIFO error flag */
+ regs_dma->IFCR = DMA_FLAG_FEIF0_4 << (hdma->StreamIndex & 0x1FU);
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_FE;
+ }
+ }
+ /* Direct Mode Error Interrupt management ***********************************/
+ if ((tmpisr_dma & (DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != 0U)
+ {
+ /* Clear the direct mode error flag */
+ regs_dma->IFCR = DMA_FLAG_DMEIF0_4 << (hdma->StreamIndex & 0x1FU);
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_DME;
+ }
+ }
+ /* Half Transfer Complete Interrupt management ******************************/
+ if ((tmpisr_dma & (DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != 0U)
+ {
+ /* Clear the half transfer complete flag */
+ regs_dma->IFCR = DMA_FLAG_HTIF0_4 << (hdma->StreamIndex & 0x1FU);
+
+ /* Multi_Buffering mode enabled */
+ if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
+ {
+ /* Current memory buffer used is Memory 0 */
+ if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
+ {
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Half transfer callback */
+ hdma->XferHalfCpltCallback(hdma);
+ }
+ }
+ /* Current memory buffer used is Memory 1 */
+ else
+ {
+ if(hdma->XferM1HalfCpltCallback != NULL)
+ {
+ /* Half transfer callback */
+ hdma->XferM1HalfCpltCallback(hdma);
+ }
+ }
+ }
+ else
+ {
+ /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
+ if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
+ {
+ /* Disable the half transfer interrupt */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT);
+ }
+
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Half transfer callback */
+ hdma->XferHalfCpltCallback(hdma);
+ }
+ }
+ }
+ }
+ /* Transfer Complete Interrupt management ***********************************/
+ if ((tmpisr_dma & (DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
+ {
+ if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != 0U)
+ {
+ /* Clear the transfer complete flag */
+ regs_dma->IFCR = DMA_FLAG_TCIF0_4 << (hdma->StreamIndex & 0x1FU);
+
+ if(HAL_DMA_STATE_ABORT == hdma->State)
+ {
+ /* Disable all the transfer interrupts */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC | DMA_IT_TE | DMA_IT_DME);
+ ((DMA_Stream_TypeDef *)hdma->Instance)->FCR &= ~(DMA_IT_FE);
+
+ if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
+ {
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_HT);
+ }
+
+ /* Clear all interrupt flags at correct offset within the register */
+ regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if(hdma->XferAbortCallback != NULL)
+ {
+ hdma->XferAbortCallback(hdma);
+ }
+ return;
+ }
+
+ if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
+ {
+ /* Current memory buffer used is Memory 1 */
+ if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) != 0U)
+ {
+ if(hdma->XferM1CpltCallback != NULL)
+ {
+ /* Transfer complete Callback for memory1 */
+ hdma->XferM1CpltCallback(hdma);
+ }
+ }
+ /* Current memory buffer used is Memory 0 */
+ else
+ {
+ 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((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
+ {
+ /* Disable the transfer complete interrupt */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+
+ if(hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete callback */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+ }
+ }
+
+ /* manage error case */
+ if(hdma->ErrorCode != HAL_DMA_ERROR_NONE)
+ {
+ if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U)
+ {
+ hdma->State = HAL_DMA_STATE_ABORT;
+
+ /* Disable the stream */
+ __HAL_DMA_DISABLE(hdma);
+
+ do
+ {
+ if (++count > timeout)
+ {
+ break;
+ }
+ }
+ while((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);
+
+ if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
+ {
+ /* Change the DMA state to error if DMA disable fails */
+ hdma->State = HAL_DMA_STATE_ERROR;
+ }
+ else
+ {
+ /* Change the DMA state to Ready if DMA disable success */
+ hdma->State = HAL_DMA_STATE_READY;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+
+ if(hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ }
+ else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
+ {
+ ccr_reg = (((BDMA_Channel_TypeDef *)hdma->Instance)->CCR);
+
+ /* Half Transfer Complete Interrupt management ******************************/
+ if (((tmpisr_bdma & (BDMA_FLAG_HT0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_HTIE) != 0U))
+ {
+ /* Clear the half transfer complete flag */
+ regs_bdma->IFCR = (BDMA_ISR_HTIF0 << (hdma->StreamIndex & 0x1FU));
+
+ /* Disable the transfer complete interrupt if the DMA mode is Double Buffering */
+ if((ccr_reg & BDMA_CCR_DBM) != 0U)
+ {
+ /* Current memory buffer used is Memory 1 */
+ if((ccr_reg & BDMA_CCR_CT) != 0U)
+ {
+ if(hdma->XferM1HalfCpltCallback != NULL)
+ {
+ /* Half transfer Callback for Memory 1 */
+ hdma->XferM1HalfCpltCallback(hdma);
+ }
+ }
+ /* Current memory buffer used is Memory 0 */
+ else
+ {
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Half transfer Callback for Memory 0 */
+ hdma->XferHalfCpltCallback(hdma);
+ }
+ }
+ }
+ else
+ {
+ if((ccr_reg & BDMA_CCR_CIRC) == 0U)
+ {
+ /* Disable the half transfer interrupt */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
+ }
+
+ /* DMA peripheral state is not updated in Half Transfer */
+ /* but in Transfer Complete case */
+
+ if(hdma->XferHalfCpltCallback != NULL)
+ {
+ /* Half transfer callback */
+ hdma->XferHalfCpltCallback(hdma);
+ }
+ }
+ }
+
+ /* Transfer Complete Interrupt management ***********************************/
+ else if (((tmpisr_bdma & (BDMA_FLAG_TC0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TCIE) != 0U))
+ {
+ /* Clear the transfer complete flag */
+ regs_bdma->IFCR = (BDMA_ISR_TCIF0) << (hdma->StreamIndex & 0x1FU);
+
+ /* Disable the transfer complete interrupt if the DMA mode is Double Buffering */
+ if((ccr_reg & BDMA_CCR_DBM) != 0U)
+ {
+ /* Current memory buffer used is Memory 0 */
+ if((ccr_reg & BDMA_CCR_CT) == 0U)
+ {
+ if(hdma->XferM1CpltCallback != NULL)
+ {
+ /* Transfer complete Callback for Memory 1 */
+ hdma->XferM1CpltCallback(hdma);
+ }
+ }
+ /* Current memory buffer used is Memory 1 */
+ else
+ {
+ if(hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete Callback for Memory 0 */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+ }
+ else
+ {
+ if((ccr_reg & BDMA_CCR_CIRC) == 0U)
+ {
+ /* Disable the transfer complete and error interrupt, if the DMA mode is not CIRCULAR */
+ __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+ }
+
+ if(hdma->XferCpltCallback != NULL)
+ {
+ /* Transfer complete callback */
+ hdma->XferCpltCallback(hdma);
+ }
+ }
+ }
+ /* Transfer Error Interrupt management **************************************/
+ else if (((tmpisr_bdma & (BDMA_FLAG_TE0 << (hdma->StreamIndex & 0x1FU))) != 0U) && ((ccr_reg & BDMA_CCR_TEIE) != 0U))
+ {
+ /* When a DMA transfer error occurs */
+ /* A hardware clear of its EN bits is performed */
+ /* Disable ALL DMA IT */
+ __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
+
+ /* Clear all flags */
+ regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
+
+ /* Update error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_TE;
+
+ /* Change the DMA state */
+ hdma->State = HAL_DMA_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hdma);
+
+ if (hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ else
+ {
+ /* Nothing To Do */
+ }
+ }
+ else
+ {
+ /* Nothing To Do */
+ }
+}
+
+/**
+ * @brief Register callbacks
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @param CallbackID: User Callback identifier
+ * a DMA_HandleTypeDef structure as parameter.
+ * @param pCallback: pointer to private callback function which has pointer to
+ * a DMA_HandleTypeDef structure as parameter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma))
+{
+
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if(HAL_DMA_STATE_READY == hdma->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA_XFER_CPLT_CB_ID:
+ hdma->XferCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_HALFCPLT_CB_ID:
+ hdma->XferHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_M1CPLT_CB_ID:
+ hdma->XferM1CpltCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_M1HALFCPLT_CB_ID:
+ hdma->XferM1HalfCpltCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_ERROR_CB_ID:
+ hdma->XferErrorCallback = pCallback;
+ break;
+
+ case HAL_DMA_XFER_ABORT_CB_ID:
+ hdma->XferAbortCallback = pCallback;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma);
+
+ return status;
+}
+
+/**
+ * @brief UnRegister callbacks
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @param CallbackID: User Callback identifier
+ * a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the DMA peripheral handle */
+ if(hdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if(HAL_DMA_STATE_READY == hdma->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_DMA_XFER_CPLT_CB_ID:
+ hdma->XferCpltCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_HALFCPLT_CB_ID:
+ hdma->XferHalfCpltCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_M1CPLT_CB_ID:
+ hdma->XferM1CpltCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_M1HALFCPLT_CB_ID:
+ hdma->XferM1HalfCpltCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_ERROR_CB_ID:
+ hdma->XferErrorCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_ABORT_CB_ID:
+ hdma->XferAbortCallback = NULL;
+ break;
+
+ case HAL_DMA_XFER_ALL_CB_ID:
+ hdma->XferCpltCallback = NULL;
+ hdma->XferHalfCpltCallback = NULL;
+ hdma->XferM1CpltCallback = NULL;
+ hdma->XferM1HalfCpltCallback = NULL;
+ hdma->XferErrorCallback = NULL;
+ hdma->XferAbortCallback = NULL;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hdma);
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @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(const 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(const DMA_HandleTypeDef *hdma)
+{
+ return hdma->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup DMA_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Sets the DMA Transfer parameter.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA 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 None
+ */
+static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
+{
+ /* calculate DMA base and stream number */
+ DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hdma->StreamBaseAddress;
+ BDMA_Base_Registers *regs_bdma = (BDMA_Base_Registers *)hdma->StreamBaseAddress;
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ }
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Clear all interrupt flags at correct offset within the register */
+ regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+
+ /* Clear DBM bit */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
+
+ /* Configure DMA Stream data length */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = DataLength;
+
+ /* Memory to Peripheral */
+ if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
+ {
+ /* Configure DMA Stream destination address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = DstAddress;
+
+ /* Configure DMA Stream source address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = SrcAddress;
+ }
+ /* Peripheral to Memory */
+ else
+ {
+ /* Configure DMA Stream source address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = SrcAddress;
+
+ /* Configure DMA Stream destination address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = DstAddress;
+ }
+ }
+ else if(IS_BDMA_CHANNEL_INSTANCE(hdma->Instance) != 0U) /* BDMA instance(s) */
+ {
+ /* Clear all flags */
+ regs_bdma->IFCR = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
+
+ /* Configure DMA Channel data length */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = DataLength;
+
+ /* Memory to Peripheral */
+ if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
+ {
+ /* Configure DMA Channel destination address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = DstAddress;
+
+ /* Configure DMA Channel source address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = SrcAddress;
+ }
+ /* Peripheral to Memory*/
+ else
+ {
+ /* Configure DMA Channel source address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = SrcAddress;
+
+ /* Configure DMA Channel destination address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = DstAddress;
+ }
+ }
+ else
+ {
+ /* Nothing To Do */
+ }
+}
+
+/**
+ * @brief Returns the DMA Stream base address depending on stream number
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval Stream base address
+ */
+static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
+{
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ uint32_t stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U;
+
+ /* lookup table for necessary bitshift of flags within status registers */
+ static const uint8_t flagBitshiftOffset[8U] = {0U, 6U, 16U, 22U, 0U, 6U, 16U, 22U};
+ hdma->StreamIndex = flagBitshiftOffset[stream_number & 0x7U];
+
+ if (stream_number > 3U)
+ {
+ /* return pointer to HISR and HIFCR */
+ hdma->StreamBaseAddress = (((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU)) + 4U);
+ }
+ else
+ {
+ /* return pointer to LISR and LIFCR */
+ hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0x3FFU));
+ }
+ }
+ else /* BDMA instance(s) */
+ {
+ /* return pointer to ISR and IFCR */
+ hdma->StreamBaseAddress = ((uint32_t)((uint32_t*)hdma->Instance) & (uint32_t)(~0xFFU));
+ }
+
+ return hdma->StreamBaseAddress;
+}
+
+/**
+ * @brief Check compatibility between FIFO threshold level and size of the memory burst
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef DMA_CheckFifoParam(const DMA_HandleTypeDef *hdma)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Memory Data size equal to Byte */
+ if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_BYTE)
+ {
+ switch (hdma->Init.FIFOThreshold)
+ {
+ case DMA_FIFO_THRESHOLD_1QUARTERFULL:
+ case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
+
+ if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+
+ case DMA_FIFO_THRESHOLD_HALFFULL:
+ if (hdma->Init.MemBurst == DMA_MBURST_INC16)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+
+ case DMA_FIFO_THRESHOLD_FULL:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Memory Data size equal to Half-Word */
+ else if (hdma->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
+ {
+ switch (hdma->Init.FIFOThreshold)
+ {
+ case DMA_FIFO_THRESHOLD_1QUARTERFULL:
+ case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
+ status = HAL_ERROR;
+ break;
+
+ case DMA_FIFO_THRESHOLD_HALFFULL:
+ if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+
+ case DMA_FIFO_THRESHOLD_FULL:
+ if (hdma->Init.MemBurst == DMA_MBURST_INC16)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* Memory Data size equal to Word */
+ else
+ {
+ switch (hdma->Init.FIFOThreshold)
+ {
+ case DMA_FIFO_THRESHOLD_1QUARTERFULL:
+ case DMA_FIFO_THRESHOLD_HALFFULL:
+ case DMA_FIFO_THRESHOLD_3QUARTERSFULL:
+ status = HAL_ERROR;
+ break;
+
+ case DMA_FIFO_THRESHOLD_FULL:
+ if ((hdma->Init.MemBurst & DMA_SxCR_MBURST_1) == DMA_SxCR_MBURST_1)
+ {
+ status = HAL_ERROR;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
+{
+ uint32_t stream_number;
+ uint32_t stream_baseaddress = (uint32_t)((uint32_t*)hdma->Instance);
+
+ if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U)
+ {
+ /* BDMA Channels are connected to DMAMUX2 channels */
+ stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 8U) / 20U;
+ hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX2_Channel0) + (stream_number * 4U)));
+ hdma->DMAmuxChannelStatus = DMAMUX2_ChannelStatus;
+ hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU);
+ }
+ else
+ {
+ /* DMA1/DMA2 Streams are connected to DMAMUX1 channels */
+ stream_number = (((uint32_t)((uint32_t*)hdma->Instance) & 0xFFU) - 16U) / 24U;
+
+ if((stream_baseaddress <= ((uint32_t)DMA2_Stream7) ) && \
+ (stream_baseaddress >= ((uint32_t)DMA2_Stream0)))
+ {
+ stream_number += 8U;
+ }
+ hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_Channel0) + (stream_number * 4U)));
+ hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
+ hdma->DMAmuxChannelStatusMask = 1UL << (stream_number & 0x1FU);
+ }
+}
+
+/**
+ * @brief Updates the DMA handle with the DMAMUX request generator params
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
+{
+ uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
+
+ if((request >= DMA_REQUEST_GENERATOR0) && (request <= DMA_REQUEST_GENERATOR7))
+ {
+ if(IS_BDMA_CHANNEL_DMAMUX_INSTANCE(hdma->Instance) != 0U)
+ {
+ /* BDMA Channels are connected to DMAMUX2 request generator blocks */
+ hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX2_RequestGenerator0) + ((request - 1U) * 4U)));
+
+ hdma->DMAmuxRequestGenStatus = DMAMUX2_RequestGenStatus;
+ }
+ else
+ {
+ /* DMA1 and DMA2 Streams use DMAMUX1 request generator blocks */
+ hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
+
+ hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
+ }
+
+ hdma->DMAmuxRequestGenStatusMask = 1UL << (request - 1U);
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c
new file mode 100755
index 0000000..a134b4e
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_dma_ex.c
@@ -0,0 +1,712 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_dma_ex.c
+ * @author MCD Application Team
+ * @brief DMA Extension HAL module driver
+ * This file provides firmware functions to manage the following
+ * functionalities of the DMA Extension peripheral:
+ * + Extended features functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The DMA Extension HAL driver can be used as follows:
+ (+) Start a multi buffer transfer using the HAL_DMA_MultiBufferStart() function
+ for polling mode or HAL_DMA_MultiBufferStart_IT() for interrupt mode.
+
+ (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
+ (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
+ Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
+ to respectively enable/disable the request generator.
+
+ (+) To handle the DMAMUX Interrupts, the function HAL_DMAEx_MUX_IRQHandler should be called from
+ the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler or DMAMUX2_OVR_IRQHandler .
+ As only one interrupt line is available for all DMAMUX channels and request generators , HAL_DMA_MUX_IRQHandler should be
+ called with, as parameter, the appropriate DMA handle as many as used DMAs in the user project
+ (exception done if a given DMA is not using the DMAMUX SYNC block neither a request generator)
+
+ -@- In Memory-to-Memory transfer mode, Multi (Double) Buffer mode is not allowed.
+ -@- When Multi (Double) Buffer mode is enabled, the transfer is circular by default.
+ -@- In Multi (Double) buffer mode, it is possible to update the base address for
+ the AHB memory port on the fly (DMA_SxM0AR or DMA_SxM1AR) when the stream is enabled.
+ -@- Multi (Double) buffer mode is possible with DMA and BDMA instances.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DMAEx DMAEx
+ * @brief DMA Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private Constants ---------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup DMAEx_Private_Functions
+ * @{
+ */
+
+static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
+
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+
+/** @addtogroup DMAEx_Exported_Functions
+ * @{
+ */
+
+
+/** @addtogroup DMAEx_Exported_Functions_Group1
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the source, destination address and data length and
+ Start MultiBuffer DMA transfer
+ (+) Configure the source, destination address and data length and
+ Start MultiBuffer DMA transfer with interrupt
+ (+) Change on the fly the memory0 or memory1 address.
+ (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
+ (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
+ (+) Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
+ to respectively enable/disable the request generator.
+ (+) Handle DMAMUX interrupts using HAL_DMAEx_MUX_IRQHandler : should be called from
+ the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler or DMAMUX2_OVR_IRQHandler
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Starts the multi_buffer 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 SecondMemAddress: The second memory Buffer address in case of multi buffer Transfer
+ * @param DataLength: The length of data to be transferred from source to destination
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ __IO uint32_t *ifcRegister_Base; /* DMA Stream Interrupt Clear register */
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ /* Memory-to-memory transfer not supported in double buffering mode */
+ if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Process Locked */
+ __HAL_LOCK(hdma);
+
+ if(HAL_DMA_STATE_READY == hdma->State)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Enable the Double buffer mode */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR |= DMA_SxCR_DBM;
+
+ /* Configure DMA Stream destination address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = SecondMemAddress;
+
+ /* Calculate the interrupt clear flag register (IFCR) base address */
+ ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 8U));
+
+ /* Clear all flags */
+ *ifcRegister_Base = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+ }
+ else /* BDMA instance(s) */
+ {
+ /* Enable the Double buffer mode */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR |= (BDMA_CCR_DBM | BDMA_CCR_CIRC);
+
+ /* Configure DMA Stream destination address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM1AR = SecondMemAddress;
+
+ /* Calculate the interrupt clear flag register (IFCR) base address */
+ ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 4U));
+
+ /* Clear all flags */
+ *ifcRegister_Base = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Configure the source, destination address and the data length */
+ DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ }
+
+ /* Enable the peripheral */
+ __HAL_DMA_ENABLE(hdma);
+ }
+ else
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Starts the multi_buffer 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 SecondMemAddress: The second memory Buffer address in case of multi buffer Transfer
+ * @param DataLength: The length of data to be transferred from source to destination
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ __IO uint32_t *ifcRegister_Base; /* DMA Stream Interrupt Clear register */
+
+ /* Check the parameters */
+ assert_param(IS_DMA_BUFFER_SIZE(DataLength));
+ assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
+
+ /* Memory-to-memory transfer not supported in double buffering mode */
+ if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
+ {
+ hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hdma);
+
+ if(HAL_DMA_STATE_READY == hdma->State)
+ {
+ /* Change DMA peripheral state */
+ hdma->State = HAL_DMA_STATE_BUSY;
+
+ /* Initialize the error code */
+ hdma->ErrorCode = HAL_DMA_ERROR_NONE;
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Enable the Double buffer mode */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR |= DMA_SxCR_DBM;
+
+ /* Configure DMA Stream destination address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = SecondMemAddress;
+
+ /* Calculate the interrupt clear flag register (IFCR) base address */
+ ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 8U));
+
+ /* Clear all flags */
+ *ifcRegister_Base = 0x3FUL << (hdma->StreamIndex & 0x1FU);
+ }
+ else /* BDMA instance(s) */
+ {
+ /* Enable the Double buffer mode */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR |= (BDMA_CCR_DBM | BDMA_CCR_CIRC);
+
+ /* Configure DMA Stream destination address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM1AR = SecondMemAddress;
+
+ /* Calculate the interrupt clear flag register (IFCR) base address */
+ ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 4U));
+
+ /* Clear all flags */
+ *ifcRegister_Base = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
+ }
+
+ /* Configure the source, destination address and the data length */
+ DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength);
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+ }
+ }
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Enable Common interrupts*/
+ MODIFY_REG(((DMA_Stream_TypeDef *)hdma->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
+ ((DMA_Stream_TypeDef *)hdma->Instance)->FCR |= DMA_IT_FE;
+
+ if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
+ {
+ /*Enable Half Transfer IT if corresponding Callback is set*/
+ ((DMA_Stream_TypeDef *)hdma->Instance)->CR |= DMA_IT_HT;
+ }
+ }
+ else /* BDMA instance(s) */
+ {
+ /* Enable Common interrupts*/
+ MODIFY_REG(((BDMA_Channel_TypeDef *)hdma->Instance)->CCR, (BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE), (BDMA_CCR_TCIE | BDMA_CCR_TEIE));
+
+ if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
+ {
+ /*Enable Half Transfer IT if corresponding Callback is set*/
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CCR |= BDMA_CCR_HTIE;
+ }
+ }
+
+ if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
+ {
+ /* Check if DMAMUX Synchronization is enabled*/
+ if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
+ {
+ /* Enable DMAMUX sync overrun IT*/
+ hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
+ }
+
+ if(hdma->DMAmuxRequestGen != 0U)
+ {
+ /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
+ /* enable the request gen overrun IT*/
+ hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
+ }
+ }
+
+ /* Enable the peripheral */
+ __HAL_DMA_ENABLE(hdma);
+ }
+ else
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+
+/**
+ * @brief Change the memory0 or memory1 address on the fly.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @param Address: The new address
+ * @param memory: the memory to be changed, This parameter can be one of
+ * the following values:
+ * MEMORY0 /
+ * MEMORY1
+ * @note The MEMORY0 address can be changed only when the current transfer use
+ * MEMORY1 and the MEMORY1 address can be changed only when the current
+ * transfer use MEMORY0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef *hdma, uint32_t Address, HAL_DMA_MemoryTypeDef memory)
+{
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ if(memory == MEMORY0)
+ {
+ /* change the memory0 address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = Address;
+ }
+ else
+ {
+ /* change the memory1 address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M1AR = Address;
+ }
+ }
+ else /* BDMA instance(s) */
+ {
+ if(memory == MEMORY0)
+ {
+ /* change the memory0 address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = Address;
+ }
+ else
+ {
+ /* change the memory1 address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM1AR = Address;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the DMAMUX synchronization parameters for a given DMA stream (instance).
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @param pSyncConfig : pointer to HAL_DMA_MuxSyncConfigTypeDef : contains the DMAMUX synchronization parameters
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig)
+{
+ uint32_t syncSignalID = 0;
+ uint32_t syncPolarity = 0;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
+ assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable));
+ assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable));
+ assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber));
+
+ if(pSyncConfig->SyncEnable == ENABLE)
+ {
+ assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig->SyncPolarity));
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ assert_param(IS_DMA_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
+ }
+ else
+ {
+ assert_param(IS_BDMA_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
+ }
+ syncSignalID = pSyncConfig->SyncSignalID;
+ syncPolarity = pSyncConfig->SyncPolarity;
+ }
+
+ /*Check if the DMA state is ready */
+ if(hdma->State == HAL_DMA_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hdma);
+
+ /* Disable the synchronization and event generation before applying a new config */
+ CLEAR_BIT(hdma->DMAmuxChannel->CCR,(DMAMUX_CxCR_SE | DMAMUX_CxCR_EGE));
+
+ /* Set the new synchronization parameters (and keep the request ID filled during the Init)*/
+ MODIFY_REG( hdma->DMAmuxChannel->CCR, \
+ (~DMAMUX_CxCR_DMAREQ_ID) , \
+ (syncSignalID << DMAMUX_CxCR_SYNC_ID_Pos) | \
+ ((pSyncConfig->RequestNumber - 1U) << DMAMUX_CxCR_NBREQ_Pos) | \
+ syncPolarity | ((uint32_t)pSyncConfig->SyncEnable << DMAMUX_CxCR_SE_Pos) | \
+ ((uint32_t)pSyncConfig->EventEnable << DMAMUX_CxCR_EGE_Pos));
+
+ /* Process Locked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* Return error status */
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the DMAMUX request generator block used by the given DMA stream (instance).
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @param pRequestGeneratorConfig : pointer to HAL_DMA_MuxRequestGeneratorConfigTypeDef :
+ * contains the request generator parameters.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig)
+{
+ HAL_StatusTypeDef status;
+ HAL_DMA_StateTypeDef temp_state = hdma->State;
+
+ /* Check the parameters */
+ assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
+
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ assert_param(IS_DMA_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
+ }
+ else
+ {
+ assert_param(IS_BDMA_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
+ }
+
+
+ assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity));
+ assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber));
+
+ /* check if the DMA state is ready
+ and DMA is using a DMAMUX request generator block
+ */
+ if(hdma->DMAmuxRequestGen == 0U)
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
+
+ /* error status */
+ status = HAL_ERROR;
+ }
+ else if(((hdma->DMAmuxRequestGen->RGCR & DMAMUX_RGxCR_GE) == 0U) && (temp_state == HAL_DMA_STATE_READY))
+ {
+ /* RequestGenerator must be disable prior to the configuration i.e GE bit is 0 */
+
+ /* Process Locked */
+ __HAL_LOCK(hdma);
+
+ /* Set the request generator new parameters */
+ hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID | \
+ ((pRequestGeneratorConfig->RequestNumber - 1U) << DMAMUX_RGxCR_GNBREQ_Pos)| \
+ pRequestGeneratorConfig->Polarity;
+ /* Process Locked */
+ __HAL_UNLOCK(hdma);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Set the error code to busy */
+ hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
+
+ /* error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Enable the DMAMUX request generator block used by the given DMA stream (instance).
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
+
+ /* check if the DMA state is ready
+ and DMA is using a DMAMUX request generator block */
+ if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
+ {
+ /* Enable the request generator*/
+ hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Disable the DMAMUX request generator block used by the given DMA stream (instance).
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
+{
+ /* Check the parameters */
+ assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
+
+ /* check if the DMA state is ready
+ and DMA is using a DMAMUX request generator block */
+ if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
+ {
+ /* Disable the request generator*/
+ hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Handles DMAMUX interrupt request.
+ * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA Stream.
+ * @retval None
+ */
+void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma)
+{
+ /* Check for DMAMUX Synchronization overrun */
+ if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
+ {
+ /* Disable the synchro overrun interrupt */
+ hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
+
+ /* Clear the DMAMUX synchro overrun flag */
+ hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
+
+ if(hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+
+ if(hdma->DMAmuxRequestGen != 0)
+ {
+ /* if using a DMAMUX request generator block Check for DMAMUX request generator overrun */
+ if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
+ {
+ /* Disable the request gen overrun interrupt */
+ hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
+
+ /* Clear the DMAMUX request generator overrun flag */
+ hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
+
+ /* Update error code */
+ hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
+
+ if(hdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hdma->XferErrorCallback(hdma);
+ }
+ }
+ }
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup DMAEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Set 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_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
+{
+ if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
+ {
+ /* Configure DMA Stream data length */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->NDTR = DataLength;
+
+ /* Peripheral to Memory */
+ if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
+ {
+ /* Configure DMA Stream destination address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = DstAddress;
+
+ /* Configure DMA Stream source address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = SrcAddress;
+ }
+ /* Memory to Peripheral */
+ else
+ {
+ /* Configure DMA Stream source address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->PAR = SrcAddress;
+
+ /* Configure DMA Stream destination address */
+ ((DMA_Stream_TypeDef *)hdma->Instance)->M0AR = DstAddress;
+ }
+ }
+ else /* BDMA instance(s) */
+ {
+ /* Configure DMA Stream data length */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CNDTR = DataLength;
+
+ /* Peripheral to Memory */
+ if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
+ {
+ /* Configure DMA Stream destination address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = DstAddress;
+
+ /* Configure DMA Stream source address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = SrcAddress;
+ }
+ /* Memory to Peripheral */
+ else
+ {
+ /* Configure DMA Stream source address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CPAR = SrcAddress;
+
+ /* Configure DMA Stream destination address */
+ ((BDMA_Channel_TypeDef *)hdma->Instance)->CM0AR = DstAddress;
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_DMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c
new file mode 100755
index 0000000..d281efe
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c
@@ -0,0 +1,865 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_exti.c
+ * @author MCD Application Team
+ * @brief EXTI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the General Purpose Input/Output (EXTI) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### EXTI Peripheral features #####
+ ==============================================================================
+ [..]
+ (+) Each EXTI line can be configured within this driver.
+
+ (+) EXTI line can be configured in 3 different modes
+ (++) Interrupt (CORE1 or CORE2 in case of dual core line )
+ (++) Event (CORE1 or CORE2 in case of dual core line )
+ (++) a combination of the previous
+
+ (+) Configurable EXTI lines can be configured with 3 different triggers
+ (++) Rising
+ (++) Falling
+ (++) Both of them
+
+ (+) When set in interrupt mode, configurable EXTI lines have two diffenrents
+ interrupt pending registers which allow to distinguish which transition
+ occurs:
+ (++) Rising edge pending interrupt
+ (++) Falling
+
+ (+) EXTI lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
+ be selected through multiplexer.
+
+ (+) PendClearSource used to set the D3 Smart Run Domain autoamtic pend clear source.
+ It is applicable for line with wkaeup target is Any (CPU1 , CPU2 and D3 smart run domain).
+ Value can be one of the following:
+ (++) EXTI_D3_PENDCLR_SRC_NONE : no pend clear source is selected :
+ In this case corresponding bit of D2PMRx register is set to 0
+ (+++) On a configurable Line : the D3 domain wakeup signal is
+ automatically cleared after after the Delay + Rising Edge detect
+ (+++) On a direct Line : the D3 domain wakeup signal is
+ cleared after the direct event input signal is cleared
+
+ (++) EXTI_D3_PENDCLR_SRC_DMACH6 : no pend clear source is selected :
+ In this case corresponding bit of D2PMRx register is set to 1
+ and corresponding bits(2) of D3PCRxL/H is set to b00 :
+ DMA ch6 event selected as D3 domain pendclear source
+
+ (++) EXTI_D3_PENDCLR_SRC_DMACH7 : no pend clear source is selected :
+ In this case corresponding bit of D2PMRx register is set to 1
+ and corresponding bits(2) of D3PCRxL/H is set to b01 :
+ DMA ch7 event selected as D3 domain pendclear source
+
+ (++) EXTI_D3_PENDCLR_SRC_LPTIM4 : no pend clear source is selected :
+ In this case corresponding bit of D2PMRx register is set to 1
+ and corresponding bits(2) of D3PCRxL/H is set to b10 :
+ LPTIM4 out selected as D3 domain pendclear source
+
+ (++) EXTI_D3_PENDCLR_SRC_LPTIM5 : no pend clear source is selected :
+ In this case corresponding bit of D2PMRx register is set to 1
+ and corresponding bits(2) of D3PCRxL/H is set to b11 :
+ LPTIM5 out selected as D3 domain pendclear source
+
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+
+ (#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
+ (++) Choose the interrupt line number by setting "Line" member from
+ EXTI_ConfigTypeDef structure.
+ (++) Configure the interrupt and/or event mode using "Mode" member from
+ EXTI_ConfigTypeDef structure.
+ (++) For configurable lines, configure rising and/or falling trigger
+ "Trigger" member from EXTI_ConfigTypeDef structure.
+ (++) For EXTI lines linked to gpio, choose gpio port using "GPIOSel"
+ member from GPIO_InitTypeDef structure.
+ (++) For EXTI lines with wkaeup target is Any (CPU1 , CPU2 and D3 smart run domain),
+ choose gpio D3 PendClearSource using PendClearSource
+ member from EXTI_PendClear_Source structure.
+
+ (#) Get current EXTI configuration of a dedicated line using
+ HAL_EXTI_GetConfigLine().
+ (++) Provide EXTI handle as parameter.
+ (++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
+
+ (#) Clear EXTI configuration of a dedicated line using HAL_EXTI_ClearConfigLine().
+ (++) Provide EXTI handle as parameter.
+
+ (#) Register callback to treat EXTI interrupts using HAL_EXTI_RegisterCallback().
+ (++) Provide EXTI handle as first parameter.
+ (++) Provide which callback will be registered using one value from
+ EXTI_CallbackIDTypeDef.
+ (++) Provide callback function pointer.
+
+ (#) Get interrupt pending bit using HAL_EXTI_GetPending().
+
+ (#) Clear interrupt pending bit using HAL_EXTI_ClearPending().
+
+ (#) Generate software interrupt using HAL_EXTI_GenerateSWI().
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @addtogroup EXTI
+ * @{
+ */
+
+#ifdef HAL_EXTI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines ------------------------------------------------------------*/
+/** @defgroup EXTI_Private_Constants EXTI Private Constants
+ * @{
+ */
+#define EXTI_MODE_OFFSET 0x04U /* 0x10: offset between CPU IMR/EMR registers */
+#define EXTI_CONFIG_OFFSET 0x08U /* 0x20: offset between CPU Rising/Falling configuration registers */
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @addtogroup EXTI_Exported_Functions
+ * @{
+ */
+
+/** @addtogroup EXTI_Exported_Functions_Group1
+ * @brief Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Configuration functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Set configuration of a dedicated EXTI line.
+ * @param hexti EXTI handle.
+ * @param pExtiConfig Pointer on EXTI configuration to be set.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+ uint32_t pcrlinepos;
+
+ /* Check null pointer */
+ if ((hexti == NULL) || (pExtiConfig == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_EXTI_LINE(pExtiConfig->Line));
+ assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
+
+ /* Assign line number to handle */
+ hexti->Line = pExtiConfig->Line;
+
+ /* compute line register offset and line mask */
+ offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
+ maskline = (1UL << linepos);
+
+ /* Configure triggers for configurable lines */
+ if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00U)
+ {
+ assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
+
+ /* Configure rising trigger */
+ regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00U)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store rising trigger mode */
+ *regaddr = regval;
+
+ /* Configure falling trigger */
+ regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00U)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store falling trigger mode */
+ *regaddr = regval;
+
+ /* Configure gpio port selection in case of gpio exti line */
+ if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
+ {
+ assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
+ assert_param(IS_EXTI_GPIO_PIN(linepos));
+
+ regval = SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL];
+ regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
+ regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03U)));
+ SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
+ }
+ }
+
+ /* Configure interrupt mode : read current mode */
+ regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00U)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store interrupt mode */
+ *regaddr = regval;
+
+ /* The event mode cannot be configured if the line does not support it */
+ assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
+
+ /* Configure event mode : read current mode */
+ regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00U)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store event mode */
+ *regaddr = regval;
+
+#if defined (DUAL_CORE)
+ /* Configure interrupt mode for Core2 : read current mode */
+ regaddr = (__IO uint32_t *)(&EXTI->C2IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Mode & EXTI_MODE_CORE2_INTERRUPT) != 0x00U)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store interrupt mode */
+ *regaddr = regval;
+
+ /* The event mode cannot be configured if the line does not support it */
+ assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_CORE2_EVENT) != EXTI_MODE_CORE2_EVENT));
+
+ /* Configure event mode : read current mode */
+ regaddr = (__IO uint32_t *)(&EXTI->C2EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Mask or set line */
+ if ((pExtiConfig->Mode & EXTI_MODE_CORE2_EVENT) != 0x00U)
+ {
+ regval |= maskline;
+ }
+ else
+ {
+ regval &= ~maskline;
+ }
+
+ /* Store event mode */
+ *regaddr = regval;
+#endif /* DUAL_CORE */
+
+ /* Configure the D3 PendClear source in case of Wakeup target is Any */
+ if ((pExtiConfig->Line & EXTI_TARGET_MASK) == EXTI_TARGET_MSK_ALL)
+ {
+ assert_param(IS_EXTI_D3_PENDCLR_SRC(pExtiConfig->PendClearSource));
+
+ /*Calc the PMR register address for the given line */
+ regaddr = (__IO uint32_t *)(&EXTI->D3PMR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ if(pExtiConfig->PendClearSource == EXTI_D3_PENDCLR_SRC_NONE)
+ {
+ /* Clear D3PMRx register for the given line */
+ regval &= ~maskline;
+ /* Store D3PMRx register value */
+ *regaddr = regval;
+ }
+ else
+ {
+ /* Set D3PMRx register to 1 for the given line */
+ regval |= maskline;
+ /* Store D3PMRx register value */
+ *regaddr = regval;
+
+ if(linepos < 16UL)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PCR1L + (EXTI_CONFIG_OFFSET * offset));
+ pcrlinepos = 1UL << linepos;
+ }
+ else
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PCR1H + (EXTI_CONFIG_OFFSET * offset));
+ pcrlinepos = 1UL << (linepos - 16UL);
+ }
+
+ regval = (*regaddr & (~(pcrlinepos * pcrlinepos * 3UL))) | (pcrlinepos * pcrlinepos * (pExtiConfig->PendClearSource - 1UL));
+ *regaddr = regval;
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Get configuration of a dedicated EXTI line.
+ * @param hexti EXTI handle.
+ * @param pExtiConfig Pointer on structure to store EXTI configuration.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+ uint32_t pcrlinepos;
+
+ /* Check null pointer */
+ if ((hexti == NULL) || (pExtiConfig == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+
+ /* Store handle line number to configuration structure */
+ pExtiConfig->Line = hexti->Line;
+
+ /* compute line register offset and line mask */
+ offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
+ maskline = (1UL << linepos);
+
+ /* 1] Get core mode : interrupt */
+ regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ pExtiConfig->Mode = EXTI_MODE_NONE;
+
+ /* Check if selected line is enable */
+ if ((regval & maskline) != 0x00U)
+ {
+ pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
+ }
+
+ /* Get event mode */
+ regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if selected line is enable */
+ if ((regval & maskline) != 0x00U)
+ {
+ pExtiConfig->Mode |= EXTI_MODE_EVENT;
+ }
+#if defined (DUAL_CORE)
+ regaddr = (__IO uint32_t *)(&EXTI->C2IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if selected line is enable */
+ if ((regval & maskline) != 0x00U)
+ {
+ pExtiConfig->Mode = EXTI_MODE_CORE2_INTERRUPT;
+ }
+
+ /* Get event mode */
+ regaddr = (__IO uint32_t *)(&EXTI->C2EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if selected line is enable */
+ if ((regval & maskline) != 0x00U)
+ {
+ pExtiConfig->Mode |= EXTI_MODE_CORE2_EVENT;
+ }
+#endif /*DUAL_CORE*/
+
+ /* Get default Trigger and GPIOSel configuration */
+ pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
+ pExtiConfig->GPIOSel = 0x00U;
+
+ /* 2] Get trigger for configurable lines : rising */
+ if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00U)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if configuration of selected line is enable */
+ if ((regval & maskline) != 0x00U)
+ {
+ pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
+ }
+
+ /* Get falling configuration */
+ regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = *regaddr;
+
+ /* Check if configuration of selected line is enable */
+ if ((regval & maskline) != 0x00U)
+ {
+ pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
+ }
+
+ /* Get Gpio port selection for gpio lines */
+ if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
+ {
+ assert_param(IS_EXTI_GPIO_PIN(linepos));
+
+ regval = SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL];
+ pExtiConfig->GPIOSel = (regval >> (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u))) & SYSCFG_EXTICR1_EXTI0;
+ }
+ }
+
+ /* Get default Pend Clear Source */
+ pExtiConfig->PendClearSource = EXTI_D3_PENDCLR_SRC_NONE;
+
+ /* 3] Get D3 Pend Clear source */
+ if ((pExtiConfig->Line & EXTI_TARGET_MASK) == EXTI_TARGET_MSK_ALL)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PMR1 + (EXTI_CONFIG_OFFSET * offset));
+ if(((*regaddr) & linepos) != 0UL)
+ {
+ /* if wakeup target is any and PMR set, the read pend clear source from D3PCRxL/H */
+ if(linepos < 16UL)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PCR1L + (EXTI_CONFIG_OFFSET * offset));
+ pcrlinepos = 1UL << linepos;
+ }
+ else
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PCR1H + (EXTI_CONFIG_OFFSET * offset));
+ pcrlinepos = 1UL << (linepos - 16UL);
+ }
+
+ pExtiConfig->PendClearSource = 1UL + ((*regaddr & (pcrlinepos * pcrlinepos * 3UL)) / (pcrlinepos * pcrlinepos));
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Clear whole configuration of a dedicated EXTI line.
+ * @param hexti EXTI handle.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(const EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+ uint32_t pcrlinepos;
+
+ /* Check null pointer */
+ if (hexti == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameter */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (hexti->Line & EXTI_PIN_MASK);
+ maskline = (1UL << linepos);
+
+ /* 1] Clear interrupt mode */
+ regaddr = (__IO uint32_t *)(&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ /* 2] Clear event mode */
+ regaddr = (__IO uint32_t *)(&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+#if defined (DUAL_CORE)
+ /* 1] Clear CM4 interrupt mode */
+ regaddr = (__IO uint32_t *)(&EXTI->C2IMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ /* 2] Clear CM4 event mode */
+ regaddr = (__IO uint32_t *)(&EXTI->C2EMR1 + (EXTI_MODE_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+#endif /* DUAL_CORE */
+
+ /* 3] Clear triggers in case of configurable lines */
+ if ((hexti->Line & EXTI_CONFIG) != 0x00U)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ regaddr = (__IO uint32_t *)(&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
+ regval = (*regaddr & ~maskline);
+ *regaddr = regval;
+
+ /* Get Gpio port selection for gpio lines */
+ if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
+ {
+ assert_param(IS_EXTI_GPIO_PIN(linepos));
+
+ regval = SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL];
+ regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03UL)));
+ SYSCFG->EXTICR[(linepos >> 2U) & 0x03UL] = regval;
+ }
+ }
+
+ /* 4] Clear D3 Config lines */
+ if ((hexti->Line & EXTI_TARGET_MASK) == EXTI_TARGET_MSK_ALL)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PMR1 + (EXTI_CONFIG_OFFSET * offset));
+ *regaddr = (*regaddr & ~maskline);
+
+ if(linepos < 16UL)
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PCR1L + (EXTI_CONFIG_OFFSET * offset));
+ pcrlinepos = 1UL << linepos;
+ }
+ else
+ {
+ regaddr = (__IO uint32_t *)(&EXTI->D3PCR1H + (EXTI_CONFIG_OFFSET * offset));
+ pcrlinepos = 1UL << (linepos - 16UL);
+ }
+
+ /*Clear D3 PendClear source */
+ *regaddr &= (~(pcrlinepos * pcrlinepos * 3UL));
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Register callback for a dedicated EXTI line.
+ * @param hexti EXTI handle.
+ * @param CallbackID User callback identifier.
+ * This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
+ * @param pPendingCbfn function pointer to be stored as callback.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check null pointer */
+ if (hexti == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ switch (CallbackID)
+ {
+ case HAL_EXTI_COMMON_CB_ID:
+ hexti->PendingCallback = pPendingCbfn;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+
+/**
+ * @brief Store line number as handle private field.
+ * @param hexti EXTI handle.
+ * @param ExtiLine EXTI line number.
+ * This parameter can be from 0 to @ref EXTI_LINE_NB.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
+{
+ /* Check the parameters */
+ assert_param(IS_EXTI_LINE(ExtiLine));
+
+ /* Check null pointer */
+ if (hexti == NULL)
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Store line number as handle private field */
+ hexti->Line = ExtiLine;
+
+ return HAL_OK;
+ }
+}
+
+
+/**
+ * @}
+ */
+
+/** @addtogroup EXTI_Exported_Functions_Group2
+ * @brief EXTI IO functions.
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle EXTI interrupt request.
+ * @param hexti EXTI handle.
+ * @retval none.
+ */
+void HAL_EXTI_IRQHandler(const EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
+
+#if defined(DUAL_CORE)
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ /* Get pending register address */
+ regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
+ }
+ else /* Cortex-M4*/
+ {
+ /* Get pending register address */
+ regaddr = (__IO uint32_t *)(&EXTI->C2PR1 + (EXTI_MODE_OFFSET * offset));
+ }
+#else
+ regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
+#endif /* DUAL_CORE */
+
+ /* Get pending bit */
+ regval = (*regaddr & maskline);
+
+ if (regval != 0x00U)
+ {
+ /* Clear pending bit */
+ *regaddr = maskline;
+
+ /* Call callback */
+ if (hexti->PendingCallback != NULL)
+ {
+ hexti->PendingCallback();
+ }
+ }
+}
+
+
+/**
+ * @brief Get interrupt pending bit of a dedicated line.
+ * @param hexti EXTI handle.
+ * @param Edge Specify which pending edge as to be checked.
+ * This parameter can be one of the following values:
+ * @arg @ref EXTI_TRIGGER_RISING_FALLING
+ * This parameter is kept for compatibility with other series.
+ * @retval 1 if interrupt is pending else 0.
+ */
+uint32_t HAL_EXTI_GetPending(const EXTI_HandleTypeDef *hexti, uint32_t Edge)
+{
+ const __IO uint32_t *regaddr;
+ uint32_t regval;
+ uint32_t linepos;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Edge);
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+ assert_param(IS_EXTI_PENDING_EDGE(Edge));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ linepos = (hexti->Line & EXTI_PIN_MASK);
+ maskline = (1UL << linepos);
+
+#if defined(DUAL_CORE)
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ /* Get pending register address */
+ regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
+ }
+ else /* Cortex-M4 */
+ {
+ /* Get pending register address */
+ regaddr = (__IO uint32_t *)(&EXTI->C2PR1 + (EXTI_MODE_OFFSET * offset));
+ }
+#else
+ regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
+#endif /* DUAL_CORE */
+
+ /* return 1 if bit is set else 0 */
+ regval = ((*regaddr & maskline) >> linepos);
+ return regval;
+}
+
+
+/**
+ * @brief Clear interrupt pending bit of a dedicated line.
+ * @param hexti EXTI handle.
+ * @param Edge Specify which pending edge as to be clear.
+ * This parameter can be one of the following values:
+ * @arg @ref EXTI_TRIGGER_RISING_FALLING
+ * This parameter is kept for compatibility with other series.
+ * @retval None.
+ */
+void HAL_EXTI_ClearPending(const EXTI_HandleTypeDef *hexti, uint32_t Edge)
+{
+ __IO uint32_t *regaddr;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Edge);
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+ assert_param(IS_EXTI_PENDING_EDGE(Edge));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
+
+#if defined(DUAL_CORE)
+ if (HAL_GetCurrentCPUID() == CM7_CPUID)
+ {
+ /* Get pending register address */
+ regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
+ }
+ else /* Cortex-M4 */
+ {
+ /* Get pending register address */
+ regaddr = (__IO uint32_t *)(&EXTI->C2PR1 + (EXTI_MODE_OFFSET * offset));
+ }
+#else
+ regaddr = (__IO uint32_t *)(&EXTI->PR1 + (EXTI_MODE_OFFSET * offset));
+#endif /* DUAL_CORE */
+
+ /* Clear Pending bit */
+ *regaddr = maskline;
+}
+
+/**
+ * @brief Generate a software interrupt for a dedicated line.
+ * @param hexti EXTI handle.
+ * @retval None.
+ */
+void HAL_EXTI_GenerateSWI(const EXTI_HandleTypeDef *hexti)
+{
+ __IO uint32_t *regaddr;
+ uint32_t maskline;
+ uint32_t offset;
+
+ /* Check parameters */
+ assert_param(IS_EXTI_LINE(hexti->Line));
+ assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
+
+ /* compute line register offset and line mask */
+ offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
+ maskline = (1UL << (hexti->Line & EXTI_PIN_MASK));
+
+ regaddr = (__IO uint32_t *)(&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
+ *regaddr = maskline;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_EXTI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c
new file mode 100755
index 0000000..6154a95
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash.c
@@ -0,0 +1,1276 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_flash.c
+ * @author MCD Application Team
+ * @brief FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the internal FLASH memory:
+ * + Program operations functions
+ * + Memory Control functions
+ * + Peripheral Errors functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### FLASH peripheral features #####
+ ==============================================================================
+
+ [..] The Flash memory interface manages CPU AXI 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 main features are:
+ (+) Flash memory read operations
+ (+) Flash memory program/erase operations
+ (+) Read / write protections
+ (+) Option bytes programming
+ (+) Error code correction (ECC) : Data in flash are 266-bits word
+ (10 bits added per flash word)
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver provides functions and macros to configure and program the FLASH
+ memory of all STM32H7xx devices.
+
+ (#) FLASH Memory IO Programming functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Program functions: 256-bit word only
+ (++) There Two modes of programming :
+ (+++) Polling mode using HAL_FLASH_Program() function
+ (+++) Interrupt mode using HAL_FLASH_Program_IT() function
+
+ (#) Interrupts and flags management functions :
+ (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
+ (++) Callback functions are called when the flash operations are finished :
+ HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
+ HAL_FLASH_OperationErrorCallback()
+ (++) Get error flag status by calling HAL_FLASH_GetError()
+
+ (#) Option bytes management functions :
+ (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
+ HAL_FLASH_OB_Lock() functions
+ (++) Launch the reload of the option bytes using HAL_FLASH_OB_Launch() function.
+ In this case, a reset is generated
+ [..]
+ In addition to these functions, this driver includes a set of macros allowing
+ to handle the following operations:
+ (+) Set the latency
+ (+) Enable/Disable the 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.
+ (@) The application can simultaneously request a read and a write operation through each AXI
+ interface.
+ As the Flash memory is divided into two independent banks, the embedded Flash
+ memory interface can drive different operations at the same time on each bank. For
+ example a read, write or erase operation can be executed on bank 1 while another read,
+ write or erase operation is executed on bank 2.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file in
+ * the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup FLASH FLASH
+ * @brief FLASH HAL module driver
+ * @{
+ */
+
+#ifdef HAL_FLASH_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @addtogroup FLASH_Private_Constants
+ * @{
+ */
+#define FLASH_TIMEOUT_VALUE 50000U /* 50 s */
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @addtogroup FLASH_Private_Variables
+ * @{
+ */
+FLASH_ProcessTypeDef pFlash = {.ProcedureOnGoing = FLASH_PROC_NONE,
+ .NbSectorsToErase = 0U,
+ .VoltageForErase= 0U,
+ .Sector = 0U,
+ .Address = 0U,
+ .Lock = HAL_UNLOCKED,
+ .ErrorCode = HAL_FLASH_ERROR_NONE};
+/**
+ * @}
+ */
+/* Private function prototypes -----------------------------------------------*/
+/* 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 a flash 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 FlashAddress specifies the address to be programmed.
+ * This parameter shall be aligned to the Flash word:
+ * - 256 bits for STM32H74x/5X devices (8x 32bits words)
+ * - 128 bits for STM32H7Ax/BX devices (4x 32bits words)
+ * - 256 bits for STM32H72x/3X devices (8x 32bits words)
+ * @param DataAddress specifies the address of data to be programmed.
+ * This parameter shall be 32-bit aligned
+ *
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)
+{
+ HAL_StatusTypeDef status;
+ __IO uint32_t *dest_addr = (__IO uint32_t *)FlashAddress;
+ __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
+ uint32_t bank;
+ uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(FlashAddress));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+#if defined (FLASH_OPTCR_PG_OTP)
+ if((IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress)) || (IS_FLASH_PROGRAM_ADDRESS_OTP(FlashAddress)))
+#else
+ if(IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress))
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ bank = FLASH_BANK_1;
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(TypeProgram);
+ }
+#if defined (DUAL_BANK)
+ else if(IS_FLASH_PROGRAM_ADDRESS_BANK2(FlashAddress))
+ {
+ bank = FLASH_BANK_2;
+ }
+#endif /* DUAL_BANK */
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
+
+ if(status == HAL_OK)
+ {
+#if defined (DUAL_BANK)
+ if(bank == FLASH_BANK_1)
+ {
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* Set OTP_PG bit */
+ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* Set PG bit */
+ SET_BIT(FLASH->CR1, FLASH_CR_PG);
+ }
+ }
+ else
+ {
+ /* Set PG bit */
+ SET_BIT(FLASH->CR2, FLASH_CR_PG);
+ }
+#else /* Single Bank */
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* Set OTP_PG bit */
+ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* Set PG bit */
+ SET_BIT(FLASH->CR1, FLASH_CR_PG);
+ }
+#endif /* DUAL_BANK */
+
+ __ISB();
+ __DSB();
+
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* Program an OTP word (16 bits) */
+ *(__IO uint16_t *)FlashAddress = *(__IO uint16_t*)DataAddress;
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* Program the flash word */
+ do
+ {
+ *dest_addr = *src_addr;
+ dest_addr++;
+ src_addr++;
+ row_index--;
+ } while (row_index != 0U);
+ }
+
+ __ISB();
+ __DSB();
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
+
+#if defined (DUAL_BANK)
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* If the program operation is completed, disable the OTP_PG */
+ CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ if(bank == FLASH_BANK_1)
+ {
+ /* If the program operation is completed, disable the PG */
+ CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
+ }
+ else
+ {
+ /* If the program operation is completed, disable the PG */
+ CLEAR_BIT(FLASH->CR2, FLASH_CR_PG);
+ }
+ }
+#else /* Single Bank */
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* If the program operation is completed, disable the OTP_PG */
+ CLEAR_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* If the program operation is completed, disable the PG */
+ CLEAR_BIT(FLASH->CR1, FLASH_CR_PG);
+ }
+#endif /* DUAL_BANK */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Program a flash 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 FlashAddress specifies the address to be programmed.
+ * This parameter shall be aligned to the Flash word:
+ * - 256 bits for STM32H74x/5X devices (8x 32bits words)
+ * - 128 bits for STM32H7Ax/BX devices (4x 32bits words)
+ * - 256 bits for STM32H72x/3X devices (8x 32bits words)
+ * @param DataAddress specifies the address of data to be programmed.
+ * This parameter shall be 32-bit aligned
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t FlashAddress, uint32_t DataAddress)
+{
+ HAL_StatusTypeDef status;
+ __IO uint32_t *dest_addr = (__IO uint32_t*)FlashAddress;
+ __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
+ uint32_t bank;
+ uint8_t row_index = FLASH_NB_32BITWORD_IN_FLASHWORD;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS(FlashAddress));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+#if defined (FLASH_OPTCR_PG_OTP)
+ if((IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress)) || (IS_FLASH_PROGRAM_ADDRESS_OTP(FlashAddress)))
+#else
+ if(IS_FLASH_PROGRAM_ADDRESS_BANK1(FlashAddress))
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ bank = FLASH_BANK_1;
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(TypeProgram);
+ }
+#if defined (DUAL_BANK)
+ else if(IS_FLASH_PROGRAM_ADDRESS_BANK2(FlashAddress))
+ {
+ bank = FLASH_BANK_2;
+ }
+#endif /* DUAL_BANK */
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, bank);
+
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+ else
+ {
+ pFlash.Address = FlashAddress;
+
+#if defined (DUAL_BANK)
+ if(bank == FLASH_BANK_1)
+ {
+ /* Set internal variables used by the IRQ handler */
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_BANK1;
+
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* Set OTP_PG bit */
+ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* Set PG bit */
+ SET_BIT(FLASH->CR1, FLASH_CR_PG);
+ }
+
+ /* Enable End of Operation and Error interrupts for Bank 1 */
+#if defined (FLASH_CR_OPERRIE)
+ __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
+#else
+ __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
+#endif /* FLASH_CR_OPERRIE */
+ }
+ else
+ {
+ /* Set internal variables used by the IRQ handler */
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_BANK2;
+
+ /* Set PG bit */
+ SET_BIT(FLASH->CR2, FLASH_CR_PG);
+
+ /* Enable End of Operation and Error interrupts for Bank2 */
+#if defined (FLASH_CR_OPERRIE)
+ __HAL_FLASH_ENABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
+ FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2 | FLASH_IT_OPERR_BANK2);
+#else
+ __HAL_FLASH_ENABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
+ FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2);
+#endif /* FLASH_CR_OPERRIE */
+ }
+#else /* Single Bank */
+ /* Set internal variables used by the IRQ handler */
+ pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_BANK1;
+
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* Set OTP_PG bit */
+ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_PG_OTP);
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* Set PG bit */
+ SET_BIT(FLASH->CR1, FLASH_CR_PG);
+ }
+
+ /* Enable End of Operation and Error interrupts for Bank 1 */
+#if defined (FLASH_CR_OPERRIE)
+ __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
+#else
+ __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
+#endif /* FLASH_CR_OPERRIE */
+#endif /* DUAL_BANK */
+
+ __ISB();
+ __DSB();
+
+#if defined (FLASH_OPTCR_PG_OTP)
+ if (TypeProgram == FLASH_TYPEPROGRAM_OTPWORD)
+ {
+ /* Program an OTP word (16 bits) */
+ *(__IO uint16_t *)FlashAddress = *(__IO uint16_t*)DataAddress;
+ }
+ else
+#endif /* FLASH_OPTCR_PG_OTP */
+ {
+ /* Program the flash word */
+ do
+ {
+ *dest_addr = *src_addr;
+ dest_addr++;
+ src_addr++;
+ row_index--;
+ } while (row_index != 0U);
+ }
+
+ __ISB();
+ __DSB();
+ }
+
+ return status;
+}
+
+/**
+ * @brief This function handles FLASH interrupt request.
+ * @retval None
+ */
+void HAL_FLASH_IRQHandler(void)
+{
+ uint32_t temp;
+ uint32_t errorflag;
+ FLASH_ProcedureTypeDef procedure;
+
+ /* Check FLASH Bank1 End of Operation flag */
+ if(__HAL_FLASH_GET_FLAG_BANK1(FLASH_SR_EOP) != RESET)
+ {
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_SECTERASE_BANK1)
+ {
+ /* Nb of sector to erased can be decreased */
+ pFlash.NbSectorsToErase--;
+
+ /* Check if there are still sectors to erase */
+ if(pFlash.NbSectorsToErase != 0U)
+ {
+ /* Indicate user which sector has been erased */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
+
+ /* Clear bank 1 End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
+
+ /* Increment sector number */
+ pFlash.Sector++;
+ temp = pFlash.Sector;
+ FLASH_Erase_Sector(temp, FLASH_BANK_1, pFlash.VoltageForErase);
+ }
+ else
+ {
+ /* No more sectors to Erase, user callback can be called */
+ /* Reset Sector and stop Erase sectors procedure */
+ pFlash.Sector = 0xFFFFFFFFU;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
+
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
+ }
+ }
+ else
+ {
+ procedure = pFlash.ProcedureOnGoing;
+
+ if((procedure == FLASH_PROC_MASSERASE_BANK1) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
+ {
+ /* MassErase ended. Return the selected bank */
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(FLASH_BANK_1);
+ }
+ else if(procedure == FLASH_PROC_PROGRAM_BANK1)
+ {
+ /* Program ended. Return the selected address */
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if((procedure != FLASH_PROC_SECTERASE_BANK2) && \
+ (procedure != FLASH_PROC_MASSERASE_BANK2) && \
+ (procedure != FLASH_PROC_PROGRAM_BANK2))
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
+ }
+ }
+ }
+
+#if defined (DUAL_BANK)
+ /* Check FLASH Bank2 End of Operation flag */
+ if(__HAL_FLASH_GET_FLAG_BANK2(FLASH_SR_EOP) != RESET)
+ {
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_SECTERASE_BANK2)
+ {
+ /*Nb of sector to erased can be decreased*/
+ pFlash.NbSectorsToErase--;
+
+ /* Check if there are still sectors to erase*/
+ if(pFlash.NbSectorsToErase != 0U)
+ {
+ /*Indicate user which sector has been erased*/
+ HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
+
+ /* Clear bank 2 End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
+
+ /*Increment sector number*/
+ pFlash.Sector++;
+ temp = pFlash.Sector;
+ FLASH_Erase_Sector(temp, FLASH_BANK_2, pFlash.VoltageForErase);
+ }
+ else
+ {
+ /* No more sectors to Erase, user callback can be called */
+ /* Reset Sector and stop Erase sectors procedure */
+ pFlash.Sector = 0xFFFFFFFFU;
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Sector);
+
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
+ }
+ }
+ else
+ {
+ procedure = pFlash.ProcedureOnGoing;
+
+ if((procedure == FLASH_PROC_MASSERASE_BANK2) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
+ {
+ /*MassErase ended. Return the selected bank*/
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(FLASH_BANK_2);
+ }
+ else if(procedure == FLASH_PROC_PROGRAM_BANK2)
+ {
+ /* Program ended. Return the selected address */
+ /* FLASH EOP interrupt user callback */
+ HAL_FLASH_EndOfOperationCallback(pFlash.Address);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if((procedure != FLASH_PROC_SECTERASE_BANK1) && \
+ (procedure != FLASH_PROC_MASSERASE_BANK1) && \
+ (procedure != FLASH_PROC_PROGRAM_BANK1))
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
+ }
+ }
+ }
+#endif /* DUAL_BANK */
+
+ /* Check FLASH Bank1 operation error flags */
+#if defined (FLASH_SR_OPERR)
+ errorflag = FLASH->SR1 & (FLASH_FLAG_WRPERR_BANK1 | FLASH_FLAG_PGSERR_BANK1 | FLASH_FLAG_STRBERR_BANK1 | \
+ FLASH_FLAG_INCERR_BANK1 | FLASH_FLAG_OPERR_BANK1);
+#else
+ errorflag = FLASH->SR1 & (FLASH_FLAG_WRPERR_BANK1 | FLASH_FLAG_PGSERR_BANK1 | FLASH_FLAG_STRBERR_BANK1 | \
+ FLASH_FLAG_INCERR_BANK1);
+#endif /* FLASH_SR_OPERR */
+
+ if(errorflag != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= errorflag;
+
+ /* Clear error programming flags */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(errorflag);
+
+ procedure = pFlash.ProcedureOnGoing;
+
+ if(procedure == FLASH_PROC_SECTERASE_BANK1)
+ {
+ /* Return the faulty sector */
+ temp = pFlash.Sector;
+ pFlash.Sector = 0xFFFFFFFFU;
+ }
+ else if((procedure == FLASH_PROC_MASSERASE_BANK1) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
+ {
+ /* Return the faulty bank */
+ temp = FLASH_BANK_1;
+ }
+ else
+ {
+ /* Return the faulty address */
+ temp = pFlash.Address;
+ }
+
+ /* Stop the procedure ongoing*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+
+ /* FLASH error interrupt user callback */
+ HAL_FLASH_OperationErrorCallback(temp);
+ }
+
+#if (USE_FLASH_ECC == 1U)
+ /* Check FLASH Bank1 ECC single correction error flag */
+ errorflag = FLASH->SR1 & FLASH_FLAG_SNECCERR_BANK1;
+
+ if(errorflag != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= errorflag;
+
+ /* Call User callback */
+ HAL_FLASHEx_EccCorrectionCallback();
+
+ /* Clear FLASH Bank1 ECC single correction error flag in order to allow new ECC error record */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(errorflag);
+ }
+
+ /* Check FLASH Bank1 ECC double detection error flag */
+ errorflag = FLASH->SR1 & FLASH_FLAG_DBECCERR_BANK1;
+
+ if(errorflag != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= errorflag;
+
+ /* Call User callback */
+ HAL_FLASHEx_EccDetectionCallback();
+
+ /* Clear FLASH Bank1 ECC double detection error flag in order to allow new ECC error record */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(errorflag);
+ }
+#endif /* USE_FLASH_ECC */
+
+#if defined (DUAL_BANK)
+ /* Check FLASH Bank2 operation error flags */
+#if defined (FLASH_SR_OPERR)
+ errorflag = FLASH->SR2 & ((FLASH_FLAG_WRPERR_BANK2 | FLASH_FLAG_PGSERR_BANK2 | FLASH_FLAG_STRBERR_BANK2 | \
+ FLASH_FLAG_INCERR_BANK2 | FLASH_FLAG_OPERR_BANK2) & 0x7FFFFFFFU);
+#else
+ errorflag = FLASH->SR2 & ((FLASH_FLAG_WRPERR_BANK2 | FLASH_FLAG_PGSERR_BANK2 | FLASH_FLAG_STRBERR_BANK2 | \
+ FLASH_FLAG_INCERR_BANK2) & 0x7FFFFFFFU);
+#endif /* FLASH_SR_OPERR */
+
+ if(errorflag != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= (errorflag | 0x80000000U);
+
+ /* Clear error programming flags */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(errorflag);
+
+ procedure = pFlash.ProcedureOnGoing;
+
+ if(procedure== FLASH_PROC_SECTERASE_BANK2)
+ {
+ /*return the faulty sector*/
+ temp = pFlash.Sector;
+ pFlash.Sector = 0xFFFFFFFFU;
+ }
+ else if((procedure == FLASH_PROC_MASSERASE_BANK2) || (procedure == FLASH_PROC_ALLBANK_MASSERASE))
+ {
+ /*return the faulty bank*/
+ temp = FLASH_BANK_2;
+ }
+ else
+ {
+ /*return the faulty address*/
+ temp = pFlash.Address;
+ }
+
+ /*Stop the procedure ongoing*/
+ pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
+
+ /* FLASH error interrupt user callback */
+ HAL_FLASH_OperationErrorCallback(temp);
+ }
+
+#if (USE_FLASH_ECC == 1U)
+ /* Check FLASH Bank2 ECC single correction error flag */
+ errorflag = FLASH->SR2 & FLASH_FLAG_SNECCERR_BANK2;
+
+ if(errorflag != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= (errorflag | 0x80000000U);
+
+ /* Call User callback */
+ HAL_FLASHEx_EccCorrectionCallback();
+
+ /* Clear FLASH Bank2 ECC single correction error flag in order to allow new ECC error record */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(errorflag);
+ }
+
+ /* Check FLASH Bank2 ECC double detection error flag */
+ errorflag = FLASH->SR2 & FLASH_FLAG_DBECCERR_BANK2;
+
+ if(errorflag != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= (errorflag | 0x80000000U);
+
+ /* Call User callback */
+ HAL_FLASHEx_EccDetectionCallback();
+
+ /* Clear FLASH Bank2 ECC double detection error flag in order to allow new ECC error record */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(errorflag);
+ }
+
+#endif /* USE_FLASH_ECC */
+#endif /* DUAL_BANK */
+
+ if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
+ {
+#if defined (FLASH_CR_OPERRIE)
+ /* Disable Bank1 Operation and Error source interrupt */
+ __HAL_FLASH_DISABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
+
+#if defined (DUAL_BANK)
+ /* Disable Bank2 Operation and Error source interrupt */
+ __HAL_FLASH_DISABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
+ FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2 | FLASH_IT_OPERR_BANK2);
+#endif /* DUAL_BANK */
+#else
+ /* Disable Bank1 Operation and Error source interrupt */
+ __HAL_FLASH_DISABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
+
+#if defined (DUAL_BANK)
+ /* Disable Bank2 Operation and Error source interrupt */
+ __HAL_FLASH_DISABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
+ FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2);
+#endif /* DUAL_BANK */
+#endif /* FLASH_CR_OPERRIE */
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+}
+
+/**
+ * @brief FLASH end of operation interrupt callback
+ * @param ReturnValue The value saved in this parameter depends on the ongoing procedure
+ * Mass Erase: Bank number which has been requested to erase
+ * 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
+ * @retval None
+ */
+__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FLASH operation error interrupt callback
+ * @param ReturnValue The value saved in this parameter depends on the ongoing procedure
+ * Mass Erase: Bank number which has been requested to erase
+ * Sectors Erase: Sector number which returned an error
+ * Program: Address which was selected for data program
+ * @retval None
+ */
+__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ReturnValue);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_FLASH_OperationErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
+ * @brief Management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the FLASH
+ memory operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Unlock the FLASH control registers access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Unlock(void)
+{
+ if(READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
+ {
+ /* Authorize the FLASH Bank1 Registers access */
+ WRITE_REG(FLASH->KEYR1, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR1, FLASH_KEY2);
+
+ /* Verify Flash Bank1 is unlocked */
+ if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+#if defined (DUAL_BANK)
+ if(READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
+ {
+ /* Authorize the FLASH Bank2 Registers access */
+ WRITE_REG(FLASH->KEYR2, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR2, FLASH_KEY2);
+
+ /* Verify Flash Bank2 is unlocked */
+ if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+#endif /* DUAL_BANK */
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Locks the FLASH control registers access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_Lock(void)
+{
+ /* Set the LOCK Bit to lock the FLASH Bank1 Control Register access */
+ SET_BIT(FLASH->CR1, FLASH_CR_LOCK);
+
+ /* Verify Flash Bank1 is locked */
+ if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) == 0U)
+ {
+ return HAL_ERROR;
+ }
+
+#if defined (DUAL_BANK)
+ /* Set the LOCK Bit to lock the FLASH Bank2 Control Register access */
+ SET_BIT(FLASH->CR2, FLASH_CR_LOCK);
+
+ /* Verify Flash Bank2 is locked */
+ if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) == 0U)
+ {
+ return HAL_ERROR;
+ }
+#endif /* DUAL_BANK */
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Unlock the FLASH Option Control Registers access.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
+{
+ if(READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
+ {
+ /* Authorizes the Option Byte registers programming */
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPT_KEY1);
+ WRITE_REG(FLASH->OPTKEYR, FLASH_OPT_KEY2);
+
+ /* Verify that the Option Bytes are unlocked */
+ if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) != 0U)
+ {
+ 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 */
+ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK);
+
+ /* Verify that the Option Bytes are locked */
+ if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTLOCK) == 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Launch the option bytes loading.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
+{
+ HAL_StatusTypeDef status;
+
+ /* Wait for CRC computation to be completed */
+ if (FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+#if defined (DUAL_BANK)
+ else if (FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+#endif /* DUAL_BANK */
+ else
+ {
+ status = HAL_OK;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Set OPTSTRT Bit */
+ SET_BIT(FLASH->OPTCR, FLASH_OPTCR_OPTSTART);
+
+ /* Wait for OB change operation to be completed */
+ status = FLASH_OB_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @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 HAL_FLASH_ERRORCode The returned value can be:
+ * @arg HAL_FLASH_ERROR_NONE : No error set
+ *
+ * @arg HAL_FLASH_ERROR_WRP_BANK1 : Write Protection Error on Bank 1
+ * @arg HAL_FLASH_ERROR_PGS_BANK1 : Program Sequence Error on Bank 1
+ * @arg HAL_FLASH_ERROR_STRB_BANK1 : Strobe Error on Bank 1
+ * @arg HAL_FLASH_ERROR_INC_BANK1 : Inconsistency Error on Bank 1
+ * @arg HAL_FLASH_ERROR_OPE_BANK1 : Operation Error on Bank 1
+ * @arg HAL_FLASH_ERROR_RDP_BANK1 : Read Protection Error on Bank 1
+ * @arg HAL_FLASH_ERROR_RDS_BANK1 : Read Secured Error on Bank 1
+ * @arg HAL_FLASH_ERROR_SNECC_BANK1: ECC Single Correction Error on Bank 1
+ * @arg HAL_FLASH_ERROR_DBECC_BANK1: ECC Double Detection Error on Bank 1
+ * @arg HAL_FLASH_ERROR_CRCRD_BANK1: CRC Read Error on Bank 1
+ *
+ * @arg HAL_FLASH_ERROR_WRP_BANK2 : Write Protection Error on Bank 2
+ * @arg HAL_FLASH_ERROR_PGS_BANK2 : Program Sequence Error on Bank 2
+ * @arg HAL_FLASH_ERROR_STRB_BANK2 : Strobe Error on Bank 2
+ * @arg HAL_FLASH_ERROR_INC_BANK2 : Inconsistency Error on Bank 2
+ * @arg HAL_FLASH_ERROR_OPE_BANK2 : Operation Error on Bank 2
+ * @arg HAL_FLASH_ERROR_RDP_BANK2 : Read Protection Error on Bank 2
+ * @arg HAL_FLASH_ERROR_RDS_BANK2 : Read Secured Error on Bank 2
+ * @arg HAL_FLASH_ERROR_SNECC_BANK2: SNECC Error on Bank 2
+ * @arg HAL_FLASH_ERROR_DBECC_BANK2: Double Detection ECC on Bank 2
+ * @arg HAL_FLASH_ERROR_CRCRD_BANK2: CRC Read Error on Bank 2
+ */
+
+uint32_t HAL_FLASH_GetError(void)
+{
+ return pFlash.ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @addtogroup FLASH_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Wait for a FLASH operation to complete.
+ * @param Timeout maximum flash operation timeout
+ * @param Bank flash FLASH_BANK_1 or FLASH_BANK_2
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout, uint32_t Bank)
+{
+ /* Wait for the FLASH operation to complete by polling on QW flag to be reset.
+ Even if the FLASH operation fails, the QW flag will be reset and an error
+ flag will be set */
+
+ uint32_t bsyflag = FLASH_FLAG_QW_BANK1;
+ uint32_t errorflag = 0;
+ uint32_t tickstart = HAL_GetTick();
+
+ assert_param(IS_FLASH_BANK_EXCLUSIVE(Bank));
+
+#if defined (DUAL_BANK)
+
+ if (Bank == FLASH_BANK_2)
+ {
+ /* Select bsyflag depending on Bank */
+ bsyflag = FLASH_FLAG_QW_BANK2;
+ }
+#endif /* DUAL_BANK */
+
+ while(__HAL_FLASH_GET_FLAG(bsyflag))
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Get Error Flags */
+ if (Bank == FLASH_BANK_1)
+ {
+ errorflag = FLASH->SR1 & FLASH_FLAG_ALL_ERRORS_BANK1;
+ }
+#if defined (DUAL_BANK)
+ else
+ {
+ errorflag = (FLASH->SR2 & FLASH_FLAG_ALL_ERRORS_BANK2) | 0x80000000U;
+ }
+#endif /* DUAL_BANK */
+
+ /* In case of error reported in Flash SR1 or SR2 register */
+ if((errorflag & 0x7FFFFFFFU) != 0U)
+ {
+ /*Save the error code*/
+ pFlash.ErrorCode |= errorflag;
+
+ /* Clear error programming flags */
+ __HAL_FLASH_CLEAR_FLAG(errorflag);
+
+ return HAL_ERROR;
+ }
+
+ /* Check FLASH End of Operation flag */
+ if(Bank == FLASH_BANK_1)
+ {
+ if (__HAL_FLASH_GET_FLAG_BANK1(FLASH_FLAG_EOP_BANK1))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_EOP_BANK1);
+ }
+ }
+#if defined (DUAL_BANK)
+ else
+ {
+ if (__HAL_FLASH_GET_FLAG_BANK2(FLASH_FLAG_EOP_BANK2))
+ {
+ /* Clear FLASH End of Operation pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_EOP_BANK2);
+ }
+ }
+#endif /* DUAL_BANK */
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Wait for a FLASH Option Bytes change operation to complete.
+ * @param Timeout maximum flash operation timeout
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef FLASH_OB_WaitForLastOperation(uint32_t Timeout)
+{
+ /* Get timeout */
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Wait for the FLASH Option Bytes change operation to complete by polling on OPT_BUSY flag to be reset */
+ while(READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_OPT_BUSY) != 0U)
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check option byte change error */
+ if(READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_OPTCHANGEERR) != 0U)
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_OB_CHANGE;
+
+ /* Clear the OB error flag */
+ FLASH->OPTCCR |= FLASH_OPTCCR_CLR_OPTCHANGEERR;
+
+ return HAL_ERROR;
+ }
+
+ /* If there is no error flag set */
+ return HAL_OK;
+}
+
+/**
+ * @brief Wait for a FLASH CRC computation to complete.
+ * @param Timeout maximum flash operation timeout
+ * @param Bank flash FLASH_BANK_1 or FLASH_BANK_2
+ * @retval HAL_StatusTypeDef HAL Status
+ */
+HAL_StatusTypeDef FLASH_CRC_WaitForLastOperation(uint32_t Timeout, uint32_t Bank)
+{
+ uint32_t bsyflag;
+ uint32_t tickstart = HAL_GetTick();
+
+ assert_param(IS_FLASH_BANK_EXCLUSIVE(Bank));
+
+ /* Select bsyflag depending on Bank */
+ if(Bank == FLASH_BANK_1)
+ {
+ bsyflag = FLASH_FLAG_CRC_BUSY_BANK1;
+ }
+ else
+ {
+ bsyflag = FLASH_FLAG_CRC_BUSY_BANK2;
+ }
+
+ /* Wait for the FLASH CRC computation to complete by polling on CRC_BUSY flag to be reset */
+ while(__HAL_FLASH_GET_FLAG(bsyflag))
+ {
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Check FLASH CRC read error flag */
+ if(Bank == FLASH_BANK_1)
+ {
+ if (__HAL_FLASH_GET_FLAG_BANK1(FLASH_FLAG_CRCRDERR_BANK1))
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_CRCRD_BANK1;
+
+ /* Clear FLASH CRC read error pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_CRCRDERR_BANK1);
+
+ return HAL_ERROR;
+ }
+ }
+#if defined (DUAL_BANK)
+ else
+ {
+ if (__HAL_FLASH_GET_FLAG_BANK2(FLASH_FLAG_CRCRDERR_BANK2))
+ {
+ /* Save the error code */
+ pFlash.ErrorCode |= HAL_FLASH_ERROR_CRCRD_BANK2;
+
+ /* Clear FLASH CRC read error pending bit */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_CRCRDERR_BANK2);
+
+ return HAL_ERROR;
+ }
+ }
+#endif /* DUAL_BANK */
+
+ /* If there is no error flag set */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c
new file mode 100755
index 0000000..aea21f4
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_flash_ex.c
@@ -0,0 +1,2129 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_flash_ex.c
+ * @author MCD Application Team
+ * @brief Extended FLASH HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the FLASH extension peripheral:
+ * + Extended programming operations functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### Flash Extension features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the FLASH interface for STM32H7xx
+ 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
+ (+) Global readout protection (RDP)
+ (+) Write protection
+ (+) Secure access only protection
+ (+) Bank / register swapping (when Dual-Bank)
+ (+) Cyclic Redundancy Check (CRC)
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure and program the FLASH memory
+ of all STM32H7xx devices. It includes
+ (#) FLASH Memory Erase functions:
+ (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
+ HAL_FLASH_Lock() functions
+ (++) Erase function: Sector erase, bank erase and dual-bank mass erase
+ (++) 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 per bank
+ (++) Set the Read protection Level
+ (++) Set the BOR level
+ (++) Program the user Option Bytes
+ (++) PCROP protection configuration and control per bank
+ (++) Secure area configuration and control per bank
+ (++) Core Boot address configuration
+ (++) TCM / AXI shared RAM configuration
+ (++) CPU Frequency Boost configuration
+
+ (#) FLASH Memory Lock and unlock per Bank: HAL_FLASHEx_Lock_Bank1(), HAL_FLASHEx_Unlock_Bank1(),
+ HAL_FLASHEx_Lock_Bank2() and HAL_FLASHEx_Unlock_Bank2() functions
+
+ (#) FLASH CRC computation function: Use HAL_FLASHEx_ComputeCRC() to:
+ (++) Enable CRC feature
+ (++) Program the desired burst size
+ (++) Define the user Flash Area on which the CRC has be computed
+ (++) Perform the CRC computation
+ (++) Disable CRC feature
+
+ (#) Error correction code error functions:
+ (++) Use the HAL_FLASHEx_EnableEccCorrectionInterrupt() and HAL_FLASHEx_DisableEccCorrectionInterrupt()
+ functions to enable and disable the FLASH ECC correction interruption.
+ (++) Use the HAL_FLASHEx_EnableEccDetectionInterrupt() and HAL_FLASHEx_DisableEccDetectionInterrupt()
+ functions to enable and disable the FLASH ECC Detection interruption.
+ (++) Handle ECCD interrupt by calling HAL_FLASHEx_BusFault_IRQHandler()
+ (++) Use HAL_FLASHEx_BusFault_IRQHandler() function called under BusFault_IRQHandler() interrupt subroutine
+ to handle the ECCD interrupt.
+ (++) Use HAL_FLASHEx_GetEccInfo() function to get the flash ECC fail information.
+
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file in
+ * the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_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 FLASH_TIMEOUT_VALUE 50000U /* 50 s */
+
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
+ * @{
+ */
+static void FLASH_MassErase(uint32_t VoltageRange, uint32_t Banks);
+static void FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks);
+static void FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Bank);
+static void FLASH_OB_GetWRP(uint32_t *WRPState, uint32_t *WRPSector, uint32_t Bank);
+static void FLASH_OB_RDPConfig(uint32_t RDPLevel);
+static uint32_t FLASH_OB_GetRDP(void);
+static void FLASH_OB_PCROPConfig(uint32_t PCROConfigRDP, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr, uint32_t Banks);
+static void FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROPStartAddr,uint32_t *PCROPEndAddr, uint32_t Bank);
+static void FLASH_OB_BOR_LevelConfig(uint32_t Level);
+static uint32_t FLASH_OB_GetBOR(void);
+static void FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig);
+static uint32_t FLASH_OB_GetUser(void);
+static void FLASH_OB_BootAddConfig(uint32_t BootOption, uint32_t BootAddress0, uint32_t BootAddress1);
+static void FLASH_OB_GetBootAdd(uint32_t *BootAddress0, uint32_t *BootAddress1);
+static void FLASH_OB_SecureAreaConfig(uint32_t SecureAreaConfig, uint32_t SecureAreaStartAddr, uint32_t SecureAreaEndAddr, uint32_t Banks);
+static void FLASH_OB_GetSecureArea(uint32_t *SecureAreaConfig, uint32_t *SecureAreaStartAddr, uint32_t *SecureAreaEndAddr, uint32_t Bank);
+static void FLASH_CRC_AddSector(uint32_t Sector, uint32_t Bank);
+static void FLASH_CRC_SelectAddress(uint32_t CRCStartAddr, uint32_t CRCEndAddr, uint32_t Bank);
+
+#if defined (DUAL_CORE)
+static void FLASH_OB_CM4BootAddConfig(uint32_t BootOption, uint32_t BootAddress0, uint32_t BootAddress1);
+static void FLASH_OB_GetCM4BootAdd(uint32_t *BootAddress0, uint32_t *BootAddress1);
+#endif /*DUAL_CORE*/
+
+#if defined (FLASH_OTPBL_LOCKBL)
+static void FLASH_OB_OTP_LockConfig(uint32_t OTP_Block);
+static uint32_t FLASH_OB_OTP_GetLock(void);
+#endif /* FLASH_OTPBL_LOCKBL */
+
+#if defined (FLASH_OPTSR2_TCM_AXI_SHARED)
+static void FLASH_OB_SharedRAM_Config(uint32_t SharedRamConfig);
+static uint32_t FLASH_OB_SharedRAM_GetConfig(void);
+#endif /* FLASH_OPTSR2_TCM_AXI_SHARED */
+
+#if defined (FLASH_OPTSR2_CPUFREQ_BOOST)
+static void FLASH_OB_CPUFreq_BoostConfig(uint32_t FreqBoost);
+static uint32_t FLASH_OB_CPUFreq_GetBoost(void);
+#endif /* FLASH_OPTSR2_CPUFREQ_BOOST */
+/**
+ * @}
+ */
+
+/* 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)
+ *
+ * @note For dual-bank devices, if the SWAP_BANK option byte is enabled, the parameter
+ * pEraseInit->Banks is modified accordingly. The logical bank addresses are swapped
+ * as follows:
+ * - FLASH_BANK_1 corresponds to the physical Bank2
+ * - FLASH_BANK_2 corresponds to the physical Bank1
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t sector_index;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+ assert_param(IS_FLASH_BANK(pEraseInit->Banks));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Wait for last operation to be completed on Bank1 */
+ if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+#if defined (DUAL_BANK)
+ /* Wait for last operation to be completed on Bank2 */
+ if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+#endif /* DUAL_BANK */
+
+ if(status == HAL_OK)
+ {
+ if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /* Mass erase to be done */
+ FLASH_MassErase(pEraseInit->VoltageRange, pEraseInit->Banks);
+
+ /* Wait for last operation to be completed on Bank 1 */
+ if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ /* if the erase operation is completed, disable the Bank1 BER Bit */
+ FLASH->CR1 &= (~FLASH_CR_BER);
+ }
+#if defined (DUAL_BANK)
+ /* Wait for last operation to be completed on Bank 2 */
+ if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ /* if the erase operation is completed, disable the Bank2 BER Bit */
+ FLASH->CR2 &= (~FLASH_CR_BER);
+ }
+#endif /* DUAL_BANK */
+ }
+ else
+ {
+ /*Initialization of SectorError variable*/
+ *SectorError = 0xFFFFFFFFU;
+
+ /* Erase by sector by sector to be done*/
+ for(sector_index = pEraseInit->Sector; sector_index < (pEraseInit->NbSectors + pEraseInit->Sector); sector_index++)
+ {
+ FLASH_Erase_Sector(sector_index, pEraseInit->Banks, pEraseInit->VoltageRange);
+
+ if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1);
+
+ /* If the erase operation is completed, disable the SER Bit */
+ FLASH->CR1 &= (~(FLASH_CR_SER | FLASH_CR_SNB));
+ }
+#if defined (DUAL_BANK)
+ if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2);
+
+ /* If the erase operation is completed, disable the SER Bit */
+ FLASH->CR2 &= (~(FLASH_CR_SER | FLASH_CR_SNB));
+ }
+#endif /* DUAL_BANK */
+
+ if(status != HAL_OK)
+ {
+ /* In case of error, stop erase procedure and return the faulty sector */
+ *SectorError = sector_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.
+ *
+ * @note For dual-bank devices, if the SWAP_BANK option byte is enabled, the parameter
+ * pEraseInit->Banks is modified accordingly. The logical bank addresses are swapped
+ * as follows:
+ * - FLASH_BANK_1 corresponds to the physical Bank2
+ * - FLASH_BANK_2 corresponds to the physical Bank1
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
+ assert_param(IS_FLASH_BANK(pEraseInit->Banks));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset error code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Wait for last operation to be completed on Bank 1 */
+ if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+#if defined (DUAL_BANK)
+ /* Wait for last operation to be completed on Bank 2 */
+ if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+#endif /* DUAL_BANK */
+
+ if (status != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+ }
+ else
+ {
+ if((pEraseInit->Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ /* Enable End of Operation and Error interrupts for Bank 1 */
+#if defined (FLASH_CR_OPERRIE)
+ __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1 | FLASH_IT_OPERR_BANK1);
+#else
+ __HAL_FLASH_ENABLE_IT_BANK1(FLASH_IT_EOP_BANK1 | FLASH_IT_WRPERR_BANK1 | FLASH_IT_PGSERR_BANK1 | \
+ FLASH_IT_STRBERR_BANK1 | FLASH_IT_INCERR_BANK1);
+#endif /* FLASH_CR_OPERRIE */
+ }
+#if defined (DUAL_BANK)
+ if((pEraseInit->Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Enable End of Operation and Error interrupts for Bank 2 */
+#if defined (FLASH_CR_OPERRIE)
+ __HAL_FLASH_ENABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
+ FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2 | FLASH_IT_OPERR_BANK2);
+#else
+ __HAL_FLASH_ENABLE_IT_BANK2(FLASH_IT_EOP_BANK2 | FLASH_IT_WRPERR_BANK2 | FLASH_IT_PGSERR_BANK2 | \
+ FLASH_IT_STRBERR_BANK2 | FLASH_IT_INCERR_BANK2);
+#endif /* FLASH_CR_OPERRIE */
+ }
+#endif /* DUAL_BANK */
+
+ if(pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
+ {
+ /*Mass erase to be done*/
+ if(pEraseInit->Banks == FLASH_BANK_1)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE_BANK1;
+ }
+#if defined (DUAL_BANK)
+ else if(pEraseInit->Banks == FLASH_BANK_2)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE_BANK2;
+ }
+#endif /* DUAL_BANK */
+ else
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_ALLBANK_MASSERASE;
+ }
+
+ FLASH_MassErase(pEraseInit->VoltageRange, pEraseInit->Banks);
+ }
+ else
+ {
+ /* Erase by sector to be done */
+#if defined (DUAL_BANK)
+ if(pEraseInit->Banks == FLASH_BANK_1)
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE_BANK1;
+ }
+ else
+ {
+ pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE_BANK2;
+ }
+#else
+ pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE_BANK1;
+#endif /* DUAL_BANK */
+
+ pFlash.NbSectorsToErase = pEraseInit->NbSectors;
+ pFlash.Sector = pEraseInit->Sector;
+ pFlash.VoltageForErase = pEraseInit->VoltageRange;
+
+ /* Erase first sector and wait for IT */
+ FLASH_Erase_Sector(pEraseInit->Sector, pEraseInit->Banks, pEraseInit->VoltageRange);
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Program option bytes
+ * @param pOBInit pointer to an FLASH_OBProgramInitTypeDef structure that
+ * contains the configuration information for the programming.
+ *
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
+
+ /* Process Locked */
+ __HAL_LOCK(&pFlash);
+
+ /* Reset Error Code */
+ pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
+
+ /* Wait for last operation to be completed */
+ if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+#if defined (DUAL_BANK)
+ else if(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+#endif /* DUAL_BANK */
+ else
+ {
+ status = HAL_OK;
+ }
+
+ if(status == HAL_OK)
+ {
+ /*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*/
+ FLASH_OB_EnableWRP(pOBInit->WRPSector,pOBInit->Banks);
+ }
+ else
+ {
+ /*Disable of Write protection on the selected Sector*/
+ FLASH_OB_DisableWRP(pOBInit->WRPSector, pOBInit->Banks);
+ }
+ }
+
+ /* Read protection configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_RDP) != 0U)
+ {
+ /* Configure the Read protection level */
+ FLASH_OB_RDPConfig(pOBInit->RDPLevel);
+ }
+
+ /* User Configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_USER) != 0U)
+ {
+ /* Configure the user option bytes */
+ FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig);
+ }
+
+ /* PCROP Configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0U)
+ {
+ assert_param(IS_FLASH_BANK(pOBInit->Banks));
+
+ /*Configure the Proprietary code readout protection */
+ FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr, pOBInit->Banks);
+ }
+
+ /* BOR Level configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_BOR) == OPTIONBYTE_BOR)
+ {
+ FLASH_OB_BOR_LevelConfig(pOBInit->BORLevel);
+ }
+
+#if defined(DUAL_CORE)
+ /* CM7 Boot Address configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_CM7_BOOTADD) == OPTIONBYTE_CM7_BOOTADD)
+ {
+ FLASH_OB_BootAddConfig(pOBInit->BootConfig, pOBInit->BootAddr0, pOBInit->BootAddr1);
+ }
+
+ /* CM4 Boot Address configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_CM4_BOOTADD) == OPTIONBYTE_CM4_BOOTADD)
+ {
+ FLASH_OB_CM4BootAddConfig(pOBInit->CM4BootConfig, pOBInit->CM4BootAddr0, pOBInit->CM4BootAddr1);
+ }
+#else /* Single Core*/
+ /* Boot Address configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_BOOTADD) == OPTIONBYTE_BOOTADD)
+ {
+ FLASH_OB_BootAddConfig(pOBInit->BootConfig, pOBInit->BootAddr0, pOBInit->BootAddr1);
+ }
+#endif /*DUAL_CORE*/
+
+ /* Secure area configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_SECURE_AREA) == OPTIONBYTE_SECURE_AREA)
+ {
+ FLASH_OB_SecureAreaConfig(pOBInit->SecureAreaConfig, pOBInit->SecureAreaStartAddr, pOBInit->SecureAreaEndAddr,pOBInit->Banks);
+ }
+
+#if defined(FLASH_OTPBL_LOCKBL)
+ /* OTP Block Lock configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_OTP_LOCK) == OPTIONBYTE_OTP_LOCK)
+ {
+ FLASH_OB_OTP_LockConfig(pOBInit->OTPBlockLock);
+ }
+#endif /* FLASH_OTPBL_LOCKBL */
+
+#if defined(FLASH_OPTSR2_TCM_AXI_SHARED)
+ /* TCM / AXI Shared RAM configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_SHARED_RAM) == OPTIONBYTE_SHARED_RAM)
+ {
+ FLASH_OB_SharedRAM_Config(pOBInit->SharedRamConfig);
+ }
+#endif /* FLASH_OPTSR2_TCM_AXI_SHARED */
+
+#if defined(FLASH_OPTSR2_CPUFREQ_BOOST)
+ /* CPU Frequency Boost configuration */
+ if((pOBInit->OptionType & OPTIONBYTE_FREQ_BOOST) == OPTIONBYTE_FREQ_BOOST)
+ {
+ FLASH_OB_CPUFreq_BoostConfig(pOBInit->FreqBoostState);
+ }
+#endif /* FLASH_OPTSR2_CPUFREQ_BOOST */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(&pFlash);
+
+ return status;
+}
+
+/**
+ * @brief Get the Option byte configuration
+ * @param pOBInit pointer to an FLASH_OBProgramInitTypeDef structure that
+ * contains the configuration information for the programming.
+ * @note The parameter Banks of the pOBInit structure must be set exclusively to FLASH_BANK_1 or FLASH_BANK_2,
+ * as this parameter is use to get the given Bank WRP, PCROP and secured area configuration.
+ *
+ * @retval None
+ */
+void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
+{
+ pOBInit->OptionType = (OPTIONBYTE_USER | OPTIONBYTE_RDP | OPTIONBYTE_BOR);
+
+ /* Get Read protection level */
+ pOBInit->RDPLevel = FLASH_OB_GetRDP();
+
+ /* Get the user option bytes */
+ pOBInit->USERConfig = FLASH_OB_GetUser();
+
+ /*Get BOR Level*/
+ pOBInit->BORLevel = FLASH_OB_GetBOR();
+
+#if defined (DUAL_BANK)
+ if ((pOBInit->Banks == FLASH_BANK_1) || (pOBInit->Banks == FLASH_BANK_2))
+#else
+ if (pOBInit->Banks == FLASH_BANK_1)
+#endif /* DUAL_BANK */
+ {
+ pOBInit->OptionType |= (OPTIONBYTE_WRP | OPTIONBYTE_PCROP | OPTIONBYTE_SECURE_AREA);
+
+ /* Get write protection on the selected area */
+ FLASH_OB_GetWRP(&(pOBInit->WRPState), &(pOBInit->WRPSector), pOBInit->Banks);
+
+ /* Get the Proprietary code readout protection */
+ FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr), pOBInit->Banks);
+
+ /*Get Bank Secure area*/
+ FLASH_OB_GetSecureArea(&(pOBInit->SecureAreaConfig), &(pOBInit->SecureAreaStartAddr), &(pOBInit->SecureAreaEndAddr), pOBInit->Banks);
+ }
+
+ /*Get Boot Address*/
+ FLASH_OB_GetBootAdd(&(pOBInit->BootAddr0), &(pOBInit->BootAddr1));
+#if defined(DUAL_CORE)
+ pOBInit->OptionType |= OPTIONBYTE_CM7_BOOTADD | OPTIONBYTE_CM4_BOOTADD;
+
+ /*Get CM4 Boot Address*/
+ FLASH_OB_GetCM4BootAdd(&(pOBInit->CM4BootAddr0), &(pOBInit->CM4BootAddr1));
+#else
+ pOBInit->OptionType |= OPTIONBYTE_BOOTADD;
+#endif /*DUAL_CORE*/
+
+#if defined (FLASH_OTPBL_LOCKBL)
+ pOBInit->OptionType |= OPTIONBYTE_OTP_LOCK;
+
+ /* Get OTP Block Lock */
+ pOBInit->OTPBlockLock = FLASH_OB_OTP_GetLock();
+#endif /* FLASH_OTPBL_LOCKBL */
+
+#if defined (FLASH_OPTSR2_TCM_AXI_SHARED)
+ pOBInit->OptionType |= OPTIONBYTE_SHARED_RAM;
+
+ /* Get TCM / AXI Shared RAM */
+ pOBInit->SharedRamConfig = FLASH_OB_SharedRAM_GetConfig();
+#endif /* FLASH_OPTSR2_TCM_AXI_SHARED */
+
+#if defined (FLASH_OPTSR2_CPUFREQ_BOOST)
+ pOBInit->OptionType |= OPTIONBYTE_FREQ_BOOST;
+
+ /* Get CPU Frequency Boost */
+ pOBInit->FreqBoostState = FLASH_OB_CPUFreq_GetBoost();
+#endif /* FLASH_OPTSR2_CPUFREQ_BOOST */
+}
+
+/**
+ * @brief Unlock the FLASH Bank1 control registers access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Unlock_Bank1(void)
+{
+ if(READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
+ {
+ /* Authorize the FLASH Bank1 Registers access */
+ WRITE_REG(FLASH->KEYR1, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR1, FLASH_KEY2);
+
+ /* Verify Flash Bank1 is unlocked */
+ if (READ_BIT(FLASH->CR1, FLASH_CR_LOCK) != 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Locks the FLASH Bank1 control registers access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Lock_Bank1(void)
+{
+ /* Set the LOCK Bit to lock the FLASH Bank1 Registers access */
+ SET_BIT(FLASH->CR1, FLASH_CR_LOCK);
+ return HAL_OK;
+}
+
+#if defined (DUAL_BANK)
+/**
+ * @brief Unlock the FLASH Bank2 control registers access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Unlock_Bank2(void)
+{
+ if(READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
+ {
+ /* Authorize the FLASH Bank2 Registers access */
+ WRITE_REG(FLASH->KEYR2, FLASH_KEY1);
+ WRITE_REG(FLASH->KEYR2, FLASH_KEY2);
+
+ /* Verify Flash Bank1 is unlocked */
+ if (READ_BIT(FLASH->CR2, FLASH_CR_LOCK) != 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Locks the FLASH Bank2 control registers access
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_FLASHEx_Lock_Bank2(void)
+{
+ /* Set the LOCK Bit to lock the FLASH Bank2 Registers access */
+ SET_BIT(FLASH->CR2, FLASH_CR_LOCK);
+ return HAL_OK;
+}
+#endif /* DUAL_BANK */
+
+/*
+ * @brief Perform a CRC computation on the specified FLASH memory area
+ * @param pCRCInit pointer to an FLASH_CRCInitTypeDef structure that
+ * contains the configuration information for the CRC computation.
+ * @note CRC computation uses CRC-32 (Ethernet) polynomial 0x4C11DB7
+ * @note The application should avoid running a CRC on PCROP or secure-only
+ * user Flash memory area since it may alter the expected CRC value.
+ * A special error flag (CRC read error: CRCRDERR) can be used to
+ * detect such a case.
+ * @retval HAL Status
+*/
+HAL_StatusTypeDef HAL_FLASHEx_ComputeCRC(FLASH_CRCInitTypeDef *pCRCInit, uint32_t *CRC_Result)
+{
+ HAL_StatusTypeDef status;
+ uint32_t sector_index;
+
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK_EXCLUSIVE(pCRCInit->Bank));
+ assert_param(IS_FLASH_TYPECRC(pCRCInit->TypeCRC));
+
+ /* Wait for OB change operation to be completed */
+ status = FLASH_OB_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
+
+ if (status == HAL_OK)
+ {
+ if (pCRCInit->Bank == FLASH_BANK_1)
+ {
+ /* Enable CRC feature */
+ FLASH->CR1 |= FLASH_CR_CRC_EN;
+
+ /* Clear CRC flags in Status Register: CRC end of calculation and CRC read error */
+ FLASH->CCR1 |= (FLASH_CCR_CLR_CRCEND | FLASH_CCR_CLR_CRCRDERR);
+ /* Clear burst size and type bits before setting new values */
+ FLASH->CRCCR1 &= ~(FLASH_CRCCR_CRC_BURST_Msk | FLASH_CRCCR_ALL_BANK);
+ /* Clear current CRC result, program burst size and define memory area on which CRC has to be computed */
+ FLASH->CRCCR1 |= FLASH_CRCCR_CLEAN_CRC | pCRCInit->BurstSize | pCRCInit->TypeCRC;
+
+ if (pCRCInit->TypeCRC == FLASH_CRC_SECTORS)
+ {
+ /* Clear sectors list */
+ FLASH->CRCCR1 |= FLASH_CRCCR_CLEAN_SECT;
+
+ /* Select CRC sectors */
+ for(sector_index = pCRCInit->Sector; sector_index < (pCRCInit->NbSectors + pCRCInit->Sector); sector_index++)
+ {
+ FLASH_CRC_AddSector(sector_index, FLASH_BANK_1);
+ }
+ }
+ else if (pCRCInit->TypeCRC == FLASH_CRC_BANK)
+ {
+ /* Enable Bank 1 CRC select bit */
+ FLASH->CRCCR1 |= FLASH_CRCCR_ALL_BANK;
+ }
+ else
+ {
+ /* Select CRC start and end addresses */
+ FLASH_CRC_SelectAddress(pCRCInit->CRCStartAddr, pCRCInit->CRCEndAddr, FLASH_BANK_1);
+ }
+
+ /* Start the CRC calculation */
+ FLASH->CRCCR1 |= FLASH_CRCCR_START_CRC;
+
+ /* Wait on CRC busy flag */
+ status = FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_1);
+
+ /* Return CRC result */
+ (*CRC_Result) = FLASH->CRCDATA;
+
+ /* Disable CRC feature */
+ FLASH->CR1 &= (~FLASH_CR_CRC_EN);
+
+ /* Clear CRC flags */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_CRCEND_BANK1 | FLASH_FLAG_CRCRDERR_BANK1);
+ }
+#if defined (DUAL_BANK)
+ else
+ {
+ /* Enable CRC feature */
+ FLASH->CR2 |= FLASH_CR_CRC_EN;
+
+ /* Clear CRC flags in Status Register: CRC end of calculation and CRC read error */
+ FLASH->CCR2 |= (FLASH_CCR_CLR_CRCEND | FLASH_CCR_CLR_CRCRDERR);
+ /* Clear burst size and type bits before setting new values */
+ FLASH->CRCCR2 &= ~(FLASH_CRCCR_CRC_BURST_Msk | FLASH_CRCCR_ALL_BANK);
+ /* Clear current CRC result, program burst size and define memory area on which CRC has to be computed */
+ FLASH->CRCCR2 |= FLASH_CRCCR_CLEAN_CRC | pCRCInit->BurstSize | pCRCInit->TypeCRC;
+
+ if (pCRCInit->TypeCRC == FLASH_CRC_SECTORS)
+ {
+ /* Clear sectors list */
+ FLASH->CRCCR2 |= FLASH_CRCCR_CLEAN_SECT;
+
+ /* Add CRC sectors */
+ for(sector_index = pCRCInit->Sector; sector_index < (pCRCInit->NbSectors + pCRCInit->Sector); sector_index++)
+ {
+ FLASH_CRC_AddSector(sector_index, FLASH_BANK_2);
+ }
+ }
+ else if (pCRCInit->TypeCRC == FLASH_CRC_BANK)
+ {
+ /* Enable Bank 2 CRC select bit */
+ FLASH->CRCCR2 |= FLASH_CRCCR_ALL_BANK;
+ }
+ else
+ {
+ /* Select CRC start and end addresses */
+ FLASH_CRC_SelectAddress(pCRCInit->CRCStartAddr, pCRCInit->CRCEndAddr, FLASH_BANK_2);
+ }
+
+ /* Start the CRC calculation */
+ FLASH->CRCCR2 |= FLASH_CRCCR_START_CRC;
+
+ /* Wait on CRC busy flag */
+ status = FLASH_CRC_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE, FLASH_BANK_2);
+
+ /* Return CRC result */
+ (*CRC_Result) = FLASH->CRCDATA;
+
+ /* Disable CRC feature */
+ FLASH->CR2 &= (~FLASH_CR_CRC_EN);
+
+ /* Clear CRC flags */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_CRCEND_BANK2 | FLASH_FLAG_CRCRDERR_BANK2);
+ }
+#endif /* DUAL_BANK */
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+#if (USE_FLASH_ECC == 1U)
+/** @defgroup FLASHEx_Exported_Functions_Group2 Extended ECC operation functions
+ * @brief Extended ECC operation functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended ECC operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the Extended FLASH
+ ECC Operations.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable ECC correction interrupts on FLASH BANK1 and BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_EnableEccCorrectionInterrupt(void)
+{
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_SNECCERR_BANK1);
+
+#if defined (DUAL_BANK)
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_SNECCERR_BANK2);
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Disable ECC correction interrupts on FLASH BANK1 and BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_DisableEccCorrectionInterrupt(void)
+{
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_SNECCERR_BANK1);
+
+#if defined (DUAL_BANK)
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_SNECCERR_BANK2);
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Enable ECC correction interrupt on FLASH BANK1.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_EnableEccCorrectionInterrupt_Bank1(void)
+{
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_SNECCERR_BANK1);
+}
+
+/**
+ * @brief Disable ECC correction interrupt on FLASH BANK1.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_DisableEccCorrectionInterrupt_Bank1(void)
+{
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_SNECCERR_BANK1);
+}
+
+#if defined (DUAL_BANK)
+/**
+ * @brief Enable ECC correction interrupt on FLASH BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_EnableEccCorrectionInterrupt_Bank2(void)
+{
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_SNECCERR_BANK2);
+}
+
+/**
+ * @brief Disable ECC correction interrupt on FLASH BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_DisableEccCorrectionInterrupt_Bank2(void)
+{
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_SNECCERR_BANK2);
+}
+#endif /* DUAL_BANK */
+
+/**
+ * @brief Enable ECC Detection interrupts on FLASH BANK1 and BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_EnableEccDetectionInterrupt(void)
+{
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_DBECCERR_BANK1);
+
+#if defined (DUAL_BANK)
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_DBECCERR_BANK2);
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Disable ECC Detection interrupts on FLASH BANK1 and BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_DisableEccDetectionInterrupt(void)
+{
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_DBECCERR_BANK1);
+
+#if defined (DUAL_BANK)
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_DBECCERR_BANK2);
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Enable ECC Detection interrupt on FLASH BANK1.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_EnableEccDetectionInterrupt_Bank1(void)
+{
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_DBECCERR_BANK1);
+}
+
+/**
+ * @brief Disable ECC correction interrupt on FLASH BANK1.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_DisableEccDetectionInterrupt_Bank1(void)
+{
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_DBECCERR_BANK1);
+}
+
+#if defined (DUAL_BANK)
+/**
+ * @brief Enable ECC Detection interrupt on FLASH BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_EnableEccDetectionInterrupt_Bank2(void)
+{
+ __HAL_FLASH_ENABLE_IT(FLASH_IT_DBECCERR_BANK2);
+}
+
+/**
+ * @brief Disable ECC Detection interrupt on FLASH BANK2.
+ * @param None
+ * @retval None
+ */
+void HAL_FLASHEx_DisableEccDetectionInterrupt_Bank2(void)
+{
+ __HAL_FLASH_DISABLE_IT(FLASH_IT_DBECCERR_BANK2);
+}
+#endif /* DUAL_BANK */
+
+/**
+ * @brief Get the ECC error information.
+ * @param pData Pointer to an FLASH_EccInfoTypeDef structure that contains the
+ * ECC error information.
+ * @note This function should be called before ECC bit is cleared
+ * (in callback function)
+ * @retval None
+ */
+void HAL_FLASHEx_GetEccInfo(FLASH_EccInfoTypeDef *pData)
+{
+ uint32_t errorflag;
+
+ /* Check FLASH Bank1 ECC single correction and double detection error flags */
+ errorflag = FLASH->SR1 & (FLASH_FLAG_SNECCERR_BANK1 | FLASH_FLAG_DBECCERR_BANK1);
+ if(errorflag != 0U)
+ {
+ pData->Area = FLASH_ECC_AREA_USER_BANK1;
+ pData->Address = ((((FLASH->ECC_FA1 & FLASH_ECC_FA_FAIL_ECC_ADDR))* FLASH_NB_32BITWORD_IN_FLASHWORD * 4) + FLASH_BANK1_BASE);
+ }
+#if defined (DUAL_BANK)
+ /* Check FLASH Bank2 ECC single correction and double detection error flags */
+ errorflag = FLASH->SR2 & (FLASH_FLAG_SNECCERR_BANK2 | FLASH_FLAG_DBECCERR_BANK2);
+ if(errorflag != 0U)
+ {
+ pData->Area = FLASH_ECC_AREA_USER_BANK2;
+ pData->Address = ((((FLASH->ECC_FA2 & FLASH_ECC_FA_FAIL_ECC_ADDR))* FLASH_NB_32BITWORD_IN_FLASHWORD * 4) + FLASH_BANK2_BASE);
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Handle Flash ECC Detection interrupt request.
+ * @retval None
+ */
+void HAL_FLASHEx_BusFault_IRQHandler(void)
+{
+ /* Check if the ECC double error occurred*/
+ if ((FLASH->SR1 & FLASH_FLAG_DBECCERR_BANK1) != 0)
+ {
+ /* FLASH ECC detection user callback */
+ HAL_FLASHEx_EccDetectionCallback();
+
+ /* Clear Bank 1 ECC double detection error flag
+ note : this step will clear all the information related to the flash ECC detection
+ */
+ __HAL_FLASH_CLEAR_FLAG_BANK1(FLASH_FLAG_DBECCERR_BANK1);
+ }
+#if defined (DUAL_BANK)
+ /* Check if the ECC double error occurred*/
+ if ((FLASH->SR2 & FLASH_FLAG_DBECCERR_BANK2) != 0)
+ {
+ /* FLASH ECC detection user callback */
+ HAL_FLASHEx_EccDetectionCallback();
+
+ /* Clear Bank 2 ECC double detection error flag
+ note : this step will clear all the information related to the flash ECC detection
+ */
+ __HAL_FLASH_CLEAR_FLAG_BANK2(FLASH_FLAG_DBECCERR_BANK2);
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief FLASH ECC Correction interrupt callback.
+ * @retval None
+ */
+__weak void HAL_FLASHEx_EccCorrectionCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_FLASHEx_EccCorrectionCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief FLASH ECC Detection interrupt callback.
+ * @retval None
+ */
+__weak void HAL_FLASHEx_EccDetectionCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_FLASHEx_EccDetectionCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+#endif /* USE_FLASH_ECC */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+
+/** @addtogroup FLASHEx_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Mass erase of FLASH memory
+ * @param VoltageRange The device program/erase parallelism.
+ * This parameter can be one of the following values:
+ * @arg FLASH_VOLTAGE_RANGE_1 : Flash program/erase by 8 bits
+ * @arg FLASH_VOLTAGE_RANGE_2 : Flash program/erase by 16 bits
+ * @arg FLASH_VOLTAGE_RANGE_3 : Flash program/erase by 32 bits
+ * @arg FLASH_VOLTAGE_RANGE_4 : Flash program/erase by 64 bits
+ *
+ * @param Banks Banks to be erased
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: Bank1 to be erased
+ * @arg FLASH_BANK_2: Bank2 to be erased
+ * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased
+ *
+ * @retval HAL Status
+ */
+static void FLASH_MassErase(uint32_t VoltageRange, uint32_t Banks)
+{
+ /* Check the parameters */
+#if defined (FLASH_CR_PSIZE)
+ assert_param(IS_VOLTAGERANGE(VoltageRange));
+#else
+ UNUSED(VoltageRange);
+#endif /* FLASH_CR_PSIZE */
+ assert_param(IS_FLASH_BANK(Banks));
+
+#if defined (DUAL_BANK)
+ /* Flash Mass Erase */
+ if((Banks & FLASH_BANK_BOTH) == FLASH_BANK_BOTH)
+ {
+#if defined (FLASH_CR_PSIZE)
+ /* Reset Program/erase VoltageRange for Bank1 and Bank2 */
+ FLASH->CR1 &= (~FLASH_CR_PSIZE);
+ FLASH->CR2 &= (~FLASH_CR_PSIZE);
+
+ /* Set voltage range */
+ FLASH->CR1 |= VoltageRange;
+ FLASH->CR2 |= VoltageRange;
+#endif /* FLASH_CR_PSIZE */
+
+ /* Set Mass Erase Bit */
+ FLASH->OPTCR |= FLASH_OPTCR_MER;
+ }
+ else
+#endif /* DUAL_BANK */
+ {
+ /* Proceed to erase Flash Bank */
+ if((Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+#if defined (FLASH_CR_PSIZE)
+ /* Set Program/erase VoltageRange for Bank1 */
+ FLASH->CR1 &= (~FLASH_CR_PSIZE);
+ FLASH->CR1 |= VoltageRange;
+#endif /* FLASH_CR_PSIZE */
+
+ /* Erase Bank1 */
+ FLASH->CR1 |= (FLASH_CR_BER | FLASH_CR_START);
+ }
+
+#if defined (DUAL_BANK)
+ if((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+#if defined (FLASH_CR_PSIZE)
+ /* Set Program/erase VoltageRange for Bank2 */
+ FLASH->CR2 &= (~FLASH_CR_PSIZE);
+ FLASH->CR2 |= VoltageRange;
+#endif /* FLASH_CR_PSIZE */
+
+ /* Erase Bank2 */
+ FLASH->CR2 |= (FLASH_CR_BER | FLASH_CR_START);
+ }
+#endif /* DUAL_BANK */
+ }
+}
+
+/**
+ * @brief Erase the specified FLASH memory sector
+ * @param Sector FLASH sector to erase
+ * This parameter can be a value of @ref FLASH_Sectors
+ * @param Banks Banks to be erased
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: Bank1 to be erased
+ * @arg FLASH_BANK_2: Bank2 to be erased
+ * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased
+ * @param VoltageRange The device program/erase parallelism.
+ * This parameter can be one of the following values:
+ * @arg FLASH_VOLTAGE_RANGE_1 : Flash program/erase by 8 bits
+ * @arg FLASH_VOLTAGE_RANGE_2 : Flash program/erase by 16 bits
+ * @arg FLASH_VOLTAGE_RANGE_3 : Flash program/erase by 32 bits
+ * @arg FLASH_VOLTAGE_RANGE_4 : Flash program/erase by 64 bits
+ *
+ * @retval None
+ */
+void FLASH_Erase_Sector(uint32_t Sector, uint32_t Banks, uint32_t VoltageRange)
+{
+ assert_param(IS_FLASH_SECTOR(Sector));
+ assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));
+#if defined (FLASH_CR_PSIZE)
+ assert_param(IS_VOLTAGERANGE(VoltageRange));
+#else
+ UNUSED(VoltageRange);
+#endif /* FLASH_CR_PSIZE */
+
+ if((Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+#if defined (FLASH_CR_PSIZE)
+ /* Reset Program/erase VoltageRange and Sector Number for Bank1 */
+ FLASH->CR1 &= ~(FLASH_CR_PSIZE | FLASH_CR_SNB);
+
+ FLASH->CR1 |= (FLASH_CR_SER | VoltageRange | (Sector << FLASH_CR_SNB_Pos) | FLASH_CR_START);
+#else
+ /* Reset Sector Number for Bank1 */
+ FLASH->CR1 &= ~(FLASH_CR_SNB);
+
+ FLASH->CR1 |= (FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos) | FLASH_CR_START);
+#endif /* FLASH_CR_PSIZE */
+ }
+
+#if defined (DUAL_BANK)
+ if((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+#if defined (FLASH_CR_PSIZE)
+ /* Reset Program/erase VoltageRange and Sector Number for Bank2 */
+ FLASH->CR2 &= ~(FLASH_CR_PSIZE | FLASH_CR_SNB);
+
+ FLASH->CR2 |= (FLASH_CR_SER | VoltageRange | (Sector << FLASH_CR_SNB_Pos) | FLASH_CR_START);
+#else
+ /* Reset Sector Number for Bank2 */
+ FLASH->CR2 &= ~(FLASH_CR_SNB);
+
+ FLASH->CR2 |= (FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos) | FLASH_CR_START);
+#endif /* FLASH_CR_PSIZE */
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Enable the write protection of the desired bank1 or bank 2 sectors
+ * @param WRPSector specifies the sector(s) to be write protected.
+ * This parameter can be one of the following values:
+ * @arg WRPSector: A combination of OB_WRP_SECTOR_0 to OB_WRP_SECTOR_7 or OB_WRP_SECTOR_ALL
+ *
+ * @param Banks the specific bank to apply WRP sectors
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: enable WRP on specified bank1 sectors
+ * @arg FLASH_BANK_2: enable WRP on specified bank2 sectors
+ * @arg FLASH_BANK_BOTH: enable WRP on both bank1 and bank2 specified sectors
+ *
+ * @retval HAL FLASH State
+ */
+static void FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_WRP_SECTOR(WRPSector));
+ assert_param(IS_FLASH_BANK(Banks));
+
+ if((Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ /* Enable Write Protection for bank 1 */
+ FLASH->WPSN_PRG1 &= (~(WRPSector & FLASH_WPSN_WRPSN));
+ }
+
+#if defined (DUAL_BANK)
+ if((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Enable Write Protection for bank 2 */
+ FLASH->WPSN_PRG2 &= (~(WRPSector & FLASH_WPSN_WRPSN));
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Disable the write protection of the desired bank1 or bank 2 sectors
+ * @param WRPSector specifies the sector(s) to disable write protection.
+ * This parameter can be one of the following values:
+ * @arg WRPSector: A combination of FLASH_OB_WRP_SECTOR_0 to FLASH_OB_WRP_SECTOR_7 or FLASH_OB_WRP_SECTOR_ALL
+ *
+ * @param Banks the specific bank to apply WRP sectors
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: disable WRP on specified bank1 sectors
+ * @arg FLASH_BANK_2: disable WRP on specified bank2 sectors
+ * @arg FLASH_BANK_BOTH: disable WRP on both bank1 and bank2 specified sectors
+ *
+ * @retval HAL FLASH State
+ */
+static void FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_WRP_SECTOR(WRPSector));
+ assert_param(IS_FLASH_BANK(Banks));
+
+ if((Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ /* Disable Write Protection for bank 1 */
+ FLASH->WPSN_PRG1 |= (WRPSector & FLASH_WPSN_WRPSN);
+ }
+
+#if defined (DUAL_BANK)
+ if((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Disable Write Protection for bank 2 */
+ FLASH->WPSN_PRG2 |= (WRPSector & FLASH_WPSN_WRPSN);
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Get the write protection of the given bank 1 or bank 2 sectors
+ * @param WRPState gives the write protection state on the given bank.
+ * This parameter can be one of the following values:
+ * @arg WRPState: OB_WRPSTATE_DISABLE or OB_WRPSTATE_ENABLE
+
+ * @param WRPSector gives the write protected sector(s) on the given bank .
+ * This parameter can be one of the following values:
+ * @arg WRPSector: A combination of FLASH_OB_WRP_SECTOR_0 to FLASH_OB_WRP_SECTOR_7 or FLASH_OB_WRP_SECTOR_ALL
+ *
+ * @param Bank the specific bank to apply WRP sectors
+ * This parameter can be exclusively one of the following values:
+ * @arg FLASH_BANK_1: Get bank1 WRP sectors
+ * @arg FLASH_BANK_2: Get bank2 WRP sectors
+ * @arg FLASH_BANK_BOTH: note allowed in this functions
+ *
+ * @retval HAL FLASH State
+ */
+static void FLASH_OB_GetWRP(uint32_t *WRPState, uint32_t *WRPSector, uint32_t Bank)
+{
+ uint32_t regvalue = 0U;
+
+ if(Bank == FLASH_BANK_1)
+ {
+ regvalue = FLASH->WPSN_CUR1;
+ }
+
+#if defined (DUAL_BANK)
+ if(Bank == FLASH_BANK_2)
+ {
+ regvalue = FLASH->WPSN_CUR2;
+ }
+#endif /* DUAL_BANK */
+
+ (*WRPSector) = (~regvalue) & FLASH_WPSN_WRPSN;
+
+ if(*WRPSector == 0U)
+ {
+ (*WRPState) = OB_WRPSTATE_DISABLE;
+ }
+ else
+ {
+ (*WRPState) = OB_WRPSTATE_ENABLE;
+ }
+}
+
+/**
+ * @brief Set the read protection level.
+ *
+ * @note To configure the RDP level, the option lock bit OPTLOCK must be
+ * cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ * @note To validate the RDP level, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ * @note !!! Warning : When enabling OB_RDP level 2 it's no more possible
+ * to go back to level 1 or 0 !!!
+ *
+ * @param RDPLevel specifies the read protection level.
+ * This parameter can be one of the following values:
+ * @arg OB_RDP_LEVEL_0: No protection
+ * @arg OB_RDP_LEVEL_1: Read protection of the memory
+ * @arg OB_RDP_LEVEL_2: Full chip protection
+ *
+ * @retval HAL status
+ */
+static void FLASH_OB_RDPConfig(uint32_t RDPLevel)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_RDP_LEVEL(RDPLevel));
+
+ /* Configure the RDP level in the option bytes register */
+ MODIFY_REG(FLASH->OPTSR_PRG, FLASH_OPTSR_RDP, RDPLevel);
+}
+
+/**
+ * @brief Get the read protection level.
+ * @retval RDPLevel specifies the read protection level.
+ * This return value can be one of the following values:
+ * @arg OB_RDP_LEVEL_0: No protection
+ * @arg OB_RDP_LEVEL_1: Read protection of the memory
+ * @arg OB_RDP_LEVEL_2: Full chip protection
+ */
+static uint32_t FLASH_OB_GetRDP(void)
+{
+ uint32_t rdp_level = READ_BIT(FLASH->OPTSR_CUR, FLASH_OPTSR_RDP);
+
+ if ((rdp_level != OB_RDP_LEVEL_0) && (rdp_level != OB_RDP_LEVEL_2))
+ {
+ return (OB_RDP_LEVEL_1);
+ }
+ else
+ {
+ return rdp_level;
+ }
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Program the FLASH User Option Byte.
+ *
+ * @note To configure the user option bytes, the option lock bit OPTLOCK must
+ * be cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ *
+ * @note To validate the user option bytes, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ *
+ * @param UserType The FLASH User Option Bytes to be modified :
+ * a combination of @ref FLASHEx_OB_USER_Type
+ *
+ * @param UserConfig The FLASH User Option Bytes values:
+ * IWDG1_SW(Bit4), IWDG2_SW(Bit 5), nRST_STOP_D1(Bit 6), nRST_STDY_D1(Bit 7),
+ * FZ_IWDG_STOP(Bit 17), FZ_IWDG_SDBY(Bit 18), ST_RAM_SIZE(Bit[19:20]),
+ * SECURITY(Bit 21), BCM4(Bit 22), BCM7(Bit 23), nRST_STOP_D2(Bit 24),
+ * nRST_STDY_D2(Bit 25), IO_HSLV (Bit 29) and SWAP_BANK_OPT(Bit 31).
+ *
+ * @retval HAL status
+ */
+#else
+/**
+ * @brief Program the FLASH User Option Byte.
+ *
+ * @note To configure the user option bytes, the option lock bit OPTLOCK must
+ * be cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ *
+ * @note To validate the user option bytes, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ *
+ * @param UserType The FLASH User Option Bytes to be modified :
+ * a combination of @arg FLASHEx_OB_USER_Type
+ *
+ * @param UserConfig The FLASH User Option Bytes values:
+ * IWDG_SW(Bit4), nRST_STOP_D1(Bit 6), nRST_STDY_D1(Bit 7),
+ * FZ_IWDG_STOP(Bit 17), FZ_IWDG_SDBY(Bit 18), ST_RAM_SIZE(Bit[19:20]),
+ * SECURITY(Bit 21), IO_HSLV (Bit 29) and SWAP_BANK_OPT(Bit 31).
+ *
+ * @retval HAL status
+ */
+#endif /*DUAL_CORE*/
+static void FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig)
+{
+ uint32_t optr_reg_val = 0;
+ uint32_t optr_reg_mask = 0;
+
+ /* Check the parameters */
+ assert_param(IS_OB_USER_TYPE(UserType));
+
+ if((UserType & OB_USER_IWDG1_SW) != 0U)
+ {
+ /* IWDG_HW option byte should be modified */
+ assert_param(IS_OB_IWDG1_SOURCE(UserConfig & FLASH_OPTSR_IWDG1_SW));
+
+ /* Set value and mask for IWDG_HW option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_IWDG1_SW);
+ optr_reg_mask |= FLASH_OPTSR_IWDG1_SW;
+ }
+#if defined(DUAL_CORE)
+ if((UserType & OB_USER_IWDG2_SW) != 0U)
+ {
+ /* IWDG2_SW option byte should be modified */
+ assert_param(IS_OB_IWDG2_SOURCE(UserConfig & FLASH_OPTSR_IWDG2_SW));
+
+ /* Set value and mask for IWDG2_SW option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_IWDG2_SW);
+ optr_reg_mask |= FLASH_OPTSR_IWDG2_SW;
+ }
+#endif /*DUAL_CORE*/
+ if((UserType & OB_USER_NRST_STOP_D1) != 0U)
+ {
+ /* NRST_STOP option byte should be modified */
+ assert_param(IS_OB_STOP_D1_RESET(UserConfig & FLASH_OPTSR_NRST_STOP_D1));
+
+ /* Set value and mask for NRST_STOP option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_NRST_STOP_D1);
+ optr_reg_mask |= FLASH_OPTSR_NRST_STOP_D1;
+ }
+
+ if((UserType & OB_USER_NRST_STDBY_D1) != 0U)
+ {
+ /* NRST_STDBY option byte should be modified */
+ assert_param(IS_OB_STDBY_D1_RESET(UserConfig & FLASH_OPTSR_NRST_STBY_D1));
+
+ /* Set value and mask for NRST_STDBY option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_NRST_STBY_D1);
+ optr_reg_mask |= FLASH_OPTSR_NRST_STBY_D1;
+ }
+
+ if((UserType & OB_USER_IWDG_STOP) != 0U)
+ {
+ /* IWDG_STOP option byte should be modified */
+ assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTSR_FZ_IWDG_STOP));
+
+ /* Set value and mask for IWDG_STOP option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_FZ_IWDG_STOP);
+ optr_reg_mask |= FLASH_OPTSR_FZ_IWDG_STOP;
+ }
+
+ if((UserType & OB_USER_IWDG_STDBY) != 0U)
+ {
+ /* IWDG_STDBY option byte should be modified */
+ assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTSR_FZ_IWDG_SDBY));
+
+ /* Set value and mask for IWDG_STDBY option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_FZ_IWDG_SDBY);
+ optr_reg_mask |= FLASH_OPTSR_FZ_IWDG_SDBY;
+ }
+
+ if((UserType & OB_USER_ST_RAM_SIZE) != 0U)
+ {
+ /* ST_RAM_SIZE option byte should be modified */
+ assert_param(IS_OB_USER_ST_RAM_SIZE(UserConfig & FLASH_OPTSR_ST_RAM_SIZE));
+
+ /* Set value and mask for ST_RAM_SIZE option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_ST_RAM_SIZE);
+ optr_reg_mask |= FLASH_OPTSR_ST_RAM_SIZE;
+ }
+
+ if((UserType & OB_USER_SECURITY) != 0U)
+ {
+ /* SECURITY option byte should be modified */
+ assert_param(IS_OB_USER_SECURITY(UserConfig & FLASH_OPTSR_SECURITY));
+
+ /* Set value and mask for SECURITY option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_SECURITY);
+ optr_reg_mask |= FLASH_OPTSR_SECURITY;
+ }
+
+#if defined(DUAL_CORE)
+ if((UserType & OB_USER_BCM4) != 0U)
+ {
+ /* BCM4 option byte should be modified */
+ assert_param(IS_OB_USER_BCM4(UserConfig & FLASH_OPTSR_BCM4));
+
+ /* Set value and mask for BCM4 option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_BCM4);
+ optr_reg_mask |= FLASH_OPTSR_BCM4;
+ }
+
+ if((UserType & OB_USER_BCM7) != 0U)
+ {
+ /* BCM7 option byte should be modified */
+ assert_param(IS_OB_USER_BCM7(UserConfig & FLASH_OPTSR_BCM7));
+
+ /* Set value and mask for BCM7 option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_BCM7);
+ optr_reg_mask |= FLASH_OPTSR_BCM7;
+ }
+#endif /* DUAL_CORE */
+
+#if defined (FLASH_OPTSR_NRST_STOP_D2)
+ if((UserType & OB_USER_NRST_STOP_D2) != 0U)
+ {
+ /* NRST_STOP option byte should be modified */
+ assert_param(IS_OB_STOP_D2_RESET(UserConfig & FLASH_OPTSR_NRST_STOP_D2));
+
+ /* Set value and mask for NRST_STOP option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_NRST_STOP_D2);
+ optr_reg_mask |= FLASH_OPTSR_NRST_STOP_D2;
+ }
+
+ if((UserType & OB_USER_NRST_STDBY_D2) != 0U)
+ {
+ /* NRST_STDBY option byte should be modified */
+ assert_param(IS_OB_STDBY_D2_RESET(UserConfig & FLASH_OPTSR_NRST_STBY_D2));
+
+ /* Set value and mask for NRST_STDBY option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_NRST_STBY_D2);
+ optr_reg_mask |= FLASH_OPTSR_NRST_STBY_D2;
+ }
+#endif /* FLASH_OPTSR_NRST_STOP_D2 */
+
+#if defined (DUAL_BANK)
+ if((UserType & OB_USER_SWAP_BANK) != 0U)
+ {
+ /* SWAP_BANK_OPT option byte should be modified */
+ assert_param(IS_OB_USER_SWAP_BANK(UserConfig & FLASH_OPTSR_SWAP_BANK_OPT));
+
+ /* Set value and mask for SWAP_BANK_OPT option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_SWAP_BANK_OPT);
+ optr_reg_mask |= FLASH_OPTSR_SWAP_BANK_OPT;
+ }
+#endif /* DUAL_BANK */
+
+ if((UserType & OB_USER_IOHSLV) != 0U)
+ {
+ /* IOHSLV_OPT option byte should be modified */
+ assert_param(IS_OB_USER_IOHSLV(UserConfig & FLASH_OPTSR_IO_HSLV));
+
+ /* Set value and mask for IOHSLV_OPT option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_IO_HSLV);
+ optr_reg_mask |= FLASH_OPTSR_IO_HSLV;
+ }
+
+#if defined (FLASH_OPTSR_VDDMMC_HSLV)
+ if((UserType & OB_USER_VDDMMC_HSLV) != 0U)
+ {
+ /* VDDMMC_HSLV option byte should be modified */
+ assert_param(IS_OB_USER_VDDMMC_HSLV(UserConfig & FLASH_OPTSR_VDDMMC_HSLV));
+
+ /* Set value and mask for VDDMMC_HSLV option byte */
+ optr_reg_val |= (UserConfig & FLASH_OPTSR_VDDMMC_HSLV);
+ optr_reg_mask |= FLASH_OPTSR_VDDMMC_HSLV;
+ }
+#endif /* FLASH_OPTSR_VDDMMC_HSLV */
+
+ /* Configure the option bytes register */
+ MODIFY_REG(FLASH->OPTSR_PRG, optr_reg_mask, optr_reg_val);
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Return the FLASH User Option Byte value.
+ * @retval The FLASH User Option Bytes values
+ * IWDG1_SW(Bit4), IWDG2_SW(Bit 5), nRST_STOP_D1(Bit 6), nRST_STDY_D1(Bit 7),
+ * FZ_IWDG_STOP(Bit 17), FZ_IWDG_SDBY(Bit 18), ST_RAM_SIZE(Bit[19:20]),
+ * SECURITY(Bit 21), BCM4(Bit 22), BCM7(Bit 23), nRST_STOP_D2(Bit 24),
+ * nRST_STDY_D2(Bit 25), IO_HSLV (Bit 29) and SWAP_BANK_OPT(Bit 31).
+ */
+#else
+/**
+ * @brief Return the FLASH User Option Byte value.
+ * @retval The FLASH User Option Bytes values
+ * IWDG_SW(Bit4), nRST_STOP_D1(Bit 6), nRST_STDY_D1(Bit 7),
+ * FZ_IWDG_STOP(Bit 17), FZ_IWDG_SDBY(Bit 18), ST_RAM_SIZE(Bit[19:20]),
+ * SECURITY(Bit 21), IO_HSLV (Bit 29) and SWAP_BANK_OPT(Bit 31).
+ */
+#endif /*DUAL_CORE*/
+static uint32_t FLASH_OB_GetUser(void)
+{
+ uint32_t userConfig = READ_REG(FLASH->OPTSR_CUR);
+ userConfig &= (~(FLASH_OPTSR_BOR_LEV | FLASH_OPTSR_RDP));
+
+ return userConfig;
+}
+
+/**
+ * @brief Configure the Proprietary code readout protection of the desired addresses
+ *
+ * @note To configure the PCROP options, the option lock bit OPTLOCK must be
+ * cleared with the call of the HAL_FLASH_OB_Unlock() function.
+ * @note To validate the PCROP options, the option bytes must be reloaded
+ * through the call of the HAL_FLASH_OB_Launch() function.
+ *
+ * @param PCROPConfig specifies if the PCROP area for the given Bank shall be erased or not
+ * when RDP level decreased from Level 1 to Level 0, or after a bank erase with protection removal
+ * This parameter must be a value of @arg FLASHEx_OB_PCROP_RDP enumeration
+ *
+ * @param PCROPStartAddr specifies the start address of the Proprietary code readout protection
+ * This parameter can be an address between begin and end of the bank
+ *
+ * @param PCROPEndAddr specifies the end address of the Proprietary code readout protection
+ * This parameter can be an address between PCROPStartAddr and end of the bank
+ *
+ * @param Banks the specific bank to apply PCROP protection
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: PCROP on specified bank1 area
+ * @arg FLASH_BANK_2: PCROP on specified bank2 area
+ * @arg FLASH_BANK_BOTH: PCROP on specified bank1 and bank2 area (same config will be applied on both banks)
+ *
+ * @retval None
+ */
+static void FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr, uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK(Banks));
+ assert_param(IS_OB_PCROP_RDP(PCROPConfig));
+
+ if((Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK1(PCROPStartAddr));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK1(PCROPEndAddr));
+
+ /* Configure the Proprietary code readout protection */
+ FLASH->PRAR_PRG1 = ((PCROPStartAddr - FLASH_BANK1_BASE) >> 8) | \
+ (((PCROPEndAddr - FLASH_BANK1_BASE) >> 8) << FLASH_PRAR_PROT_AREA_END_Pos) | \
+ PCROPConfig;
+ }
+
+#if defined (DUAL_BANK)
+ if((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK2(PCROPStartAddr));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK2(PCROPEndAddr));
+
+ /* Configure the Proprietary code readout protection */
+ FLASH->PRAR_PRG2 = ((PCROPStartAddr - FLASH_BANK2_BASE) >> 8) | \
+ (((PCROPEndAddr - FLASH_BANK2_BASE) >> 8) << FLASH_PRAR_PROT_AREA_END_Pos) | \
+ PCROPConfig;
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Get the Proprietary code readout protection configuration on a given Bank
+ *
+ * @param PCROPConfig indicates if the PCROP area for the given Bank shall be erased or not
+ * when RDP level decreased from Level 1 to Level 0 or after a bank erase with protection removal
+ *
+ * @param PCROPStartAddr gives the start address of the Proprietary code readout protection of the bank
+ *
+ * @param PCROPEndAddr gives the end address of the Proprietary code readout protection of the bank
+ *
+ * @param Bank the specific bank to apply PCROP protection
+ * This parameter can be exclusively one of the following values:
+ * @arg FLASH_BANK_1: PCROP on specified bank1 area
+ * @arg FLASH_BANK_2: PCROP on specified bank2 area
+ * @arg FLASH_BANK_BOTH: is not allowed here
+ *
+ * @retval None
+ */
+static void FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROPStartAddr, uint32_t *PCROPEndAddr, uint32_t Bank)
+{
+ uint32_t regvalue = 0;
+ uint32_t bankBase = 0;
+
+ if(Bank == FLASH_BANK_1)
+ {
+ regvalue = FLASH->PRAR_CUR1;
+ bankBase = FLASH_BANK1_BASE;
+ }
+
+#if defined (DUAL_BANK)
+ if(Bank == FLASH_BANK_2)
+ {
+ regvalue = FLASH->PRAR_CUR2;
+ bankBase = FLASH_BANK2_BASE;
+ }
+#endif /* DUAL_BANK */
+
+ (*PCROPConfig) = (regvalue & FLASH_PRAR_DMEP);
+
+ (*PCROPStartAddr) = ((regvalue & FLASH_PRAR_PROT_AREA_START) << 8) + bankBase;
+ (*PCROPEndAddr) = (regvalue & FLASH_PRAR_PROT_AREA_END) >> FLASH_PRAR_PROT_AREA_END_Pos;
+ (*PCROPEndAddr) = ((*PCROPEndAddr) << 8) + bankBase;
+}
+
+/**
+ * @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_LEVEL0: Reset level threshold is set to 1.6V
+ * @arg OB_BOR_LEVEL1: Reset level threshold is set to 2.1V
+ * @arg OB_BOR_LEVEL2: Reset level threshold is set to 2.4V
+ * @arg OB_BOR_LEVEL3: Reset level threshold is set to 2.7V
+ * @retval None
+ */
+static void FLASH_OB_BOR_LevelConfig(uint32_t Level)
+{
+ assert_param(IS_OB_BOR_LEVEL(Level));
+
+ /* Configure BOR_LEV option byte */
+ MODIFY_REG(FLASH->OPTSR_PRG, FLASH_OPTSR_BOR_LEV, Level);
+}
+
+/**
+ * @brief Get the BOR Level.
+ * @retval The Option Bytes BOR Reset Level.
+ * This parameter can be one of the following values:
+ * @arg OB_BOR_LEVEL0: Reset level threshold is set to 1.6V
+ * @arg OB_BOR_LEVEL1: Reset level threshold is set to 2.1V
+ * @arg OB_BOR_LEVEL2: Reset level threshold is set to 2.4V
+ * @arg OB_BOR_LEVEL3: Reset level threshold is set to 2.7V
+ */
+static uint32_t FLASH_OB_GetBOR(void)
+{
+ return (FLASH->OPTSR_CUR & FLASH_OPTSR_BOR_LEV);
+}
+
+/**
+ * @brief Set Boot address
+ * @param BootOption Boot address option byte to be programmed,
+ * This parameter must be a value of @ref FLASHEx_OB_BOOT_OPTION
+ (OB_BOOT_ADD0, OB_BOOT_ADD1 or OB_BOOT_ADD_BOTH)
+ *
+ * @param BootAddress0 Specifies the Boot Address 0
+ * @param BootAddress1 Specifies the Boot Address 1
+ * @retval HAL Status
+ */
+static void FLASH_OB_BootAddConfig(uint32_t BootOption, uint32_t BootAddress0, uint32_t BootAddress1)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_BOOT_ADD_OPTION(BootOption));
+
+ if((BootOption & OB_BOOT_ADD0) == OB_BOOT_ADD0)
+ {
+ /* Check the parameters */
+ assert_param(IS_BOOT_ADDRESS(BootAddress0));
+
+ /* Configure CM7 BOOT ADD0 */
+#if defined(DUAL_CORE)
+ MODIFY_REG(FLASH->BOOT7_PRG, FLASH_BOOT7_BCM7_ADD0, (BootAddress0 >> 16));
+#else /* Single Core*/
+ MODIFY_REG(FLASH->BOOT_PRG, FLASH_BOOT_ADD0, (BootAddress0 >> 16));
+#endif /* DUAL_CORE */
+ }
+
+ if((BootOption & OB_BOOT_ADD1) == OB_BOOT_ADD1)
+ {
+ /* Check the parameters */
+ assert_param(IS_BOOT_ADDRESS(BootAddress1));
+
+ /* Configure CM7 BOOT ADD1 */
+#if defined(DUAL_CORE)
+ MODIFY_REG(FLASH->BOOT7_PRG, FLASH_BOOT7_BCM7_ADD1, BootAddress1);
+#else /* Single Core*/
+ MODIFY_REG(FLASH->BOOT_PRG, FLASH_BOOT_ADD1, BootAddress1);
+#endif /* DUAL_CORE */
+ }
+}
+
+/**
+ * @brief Get Boot address
+ * @param BootAddress0 Specifies the Boot Address 0.
+ * @param BootAddress1 Specifies the Boot Address 1.
+ * @retval HAL Status
+ */
+static void FLASH_OB_GetBootAdd(uint32_t *BootAddress0, uint32_t *BootAddress1)
+{
+ uint32_t regvalue;
+
+#if defined(DUAL_CORE)
+ regvalue = FLASH->BOOT7_CUR;
+
+ (*BootAddress0) = (regvalue & FLASH_BOOT7_BCM7_ADD0) << 16;
+ (*BootAddress1) = (regvalue & FLASH_BOOT7_BCM7_ADD1);
+#else /* Single Core */
+ regvalue = FLASH->BOOT_CUR;
+
+ (*BootAddress0) = (regvalue & FLASH_BOOT_ADD0) << 16;
+ (*BootAddress1) = (regvalue & FLASH_BOOT_ADD1);
+#endif /* DUAL_CORE */
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Set CM4 Boot address
+ * @param BootOption Boot address option byte to be programmed,
+ * This parameter must be a value of @ref FLASHEx_OB_BOOT_OPTION
+ (OB_BOOT_ADD0, OB_BOOT_ADD1 or OB_BOOT_ADD_BOTH)
+ *
+ * @param BootAddress0 Specifies the CM4 Boot Address 0.
+ * @param BootAddress1 Specifies the CM4 Boot Address 1.
+ * @retval HAL Status
+ */
+static void FLASH_OB_CM4BootAddConfig(uint32_t BootOption, uint32_t BootAddress0, uint32_t BootAddress1)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_BOOT_ADD_OPTION(BootOption));
+
+ if((BootOption & OB_BOOT_ADD0) == OB_BOOT_ADD0)
+ {
+ /* Check the parameters */
+ assert_param(IS_BOOT_ADDRESS(BootAddress0));
+
+ /* Configure CM4 BOOT ADD0 */
+ MODIFY_REG(FLASH->BOOT4_PRG, FLASH_BOOT4_BCM4_ADD0, (BootAddress0 >> 16));
+
+ }
+
+ if((BootOption & OB_BOOT_ADD1) == OB_BOOT_ADD1)
+ {
+ /* Check the parameters */
+ assert_param(IS_BOOT_ADDRESS(BootAddress1));
+
+ /* Configure CM4 BOOT ADD1 */
+ MODIFY_REG(FLASH->BOOT4_PRG, FLASH_BOOT4_BCM4_ADD1, BootAddress1);
+ }
+}
+
+/**
+ * @brief Get CM4 Boot address
+ * @param BootAddress0 Specifies the CM4 Boot Address 0.
+ * @param BootAddress1 Specifies the CM4 Boot Address 1.
+ * @retval HAL Status
+ */
+static void FLASH_OB_GetCM4BootAdd(uint32_t *BootAddress0, uint32_t *BootAddress1)
+{
+ uint32_t regvalue;
+
+ regvalue = FLASH->BOOT4_CUR;
+
+ (*BootAddress0) = (regvalue & FLASH_BOOT4_BCM4_ADD0) << 16;
+ (*BootAddress1) = (regvalue & FLASH_BOOT4_BCM4_ADD1);
+}
+#endif /*DUAL_CORE*/
+
+/**
+ * @brief Set secure area configuration
+ * @param SecureAreaConfig specify if the secure area will be deleted or not
+ * when RDP level decreased from Level 1 to Level 0 or during a mass erase.
+ *
+ * @param SecureAreaStartAddr Specifies the secure area start address
+ * @param SecureAreaEndAddr Specifies the secure area end address
+ * @param Banks the specific bank to apply Security protection
+ * This parameter can be one of the following values:
+ * @arg FLASH_BANK_1: Secure area on specified bank1 area
+ * @arg FLASH_BANK_2: Secure area on specified bank2 area
+ * @arg FLASH_BANK_BOTH: Secure area on specified bank1 and bank2 area (same config will be applied on both banks)
+ * @retval None
+ */
+static void FLASH_OB_SecureAreaConfig(uint32_t SecureAreaConfig, uint32_t SecureAreaStartAddr, uint32_t SecureAreaEndAddr, uint32_t Banks)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_BANK(Banks));
+ assert_param(IS_OB_SECURE_RDP(SecureAreaConfig));
+
+ if((Banks & FLASH_BANK_1) == FLASH_BANK_1)
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK1(SecureAreaStartAddr));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK1(SecureAreaEndAddr));
+
+ /* Configure the secure area */
+ FLASH->SCAR_PRG1 = ((SecureAreaStartAddr - FLASH_BANK1_BASE) >> 8) | \
+ (((SecureAreaEndAddr - FLASH_BANK1_BASE) >> 8) << FLASH_SCAR_SEC_AREA_END_Pos) | \
+ (SecureAreaConfig & FLASH_SCAR_DMES);
+ }
+
+#if defined (DUAL_BANK)
+ if((Banks & FLASH_BANK_2) == FLASH_BANK_2)
+ {
+ /* Check the parameters */
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK2(SecureAreaStartAddr));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK2(SecureAreaEndAddr));
+
+ /* Configure the secure area */
+ FLASH->SCAR_PRG2 = ((SecureAreaStartAddr - FLASH_BANK2_BASE) >> 8) | \
+ (((SecureAreaEndAddr - FLASH_BANK2_BASE) >> 8) << FLASH_SCAR_SEC_AREA_END_Pos) | \
+ (SecureAreaConfig & FLASH_SCAR_DMES);
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Get secure area configuration
+ * @param SecureAreaConfig indicates if the secure area will be deleted or not
+ * when RDP level decreased from Level 1 to Level 0 or during a mass erase.
+ * @param SecureAreaStartAddr gives the secure area start address
+ * @param SecureAreaEndAddr gives the secure area end address
+ * @param Bank Specifies the Bank
+ * @retval None
+ */
+static void FLASH_OB_GetSecureArea(uint32_t *SecureAreaConfig, uint32_t *SecureAreaStartAddr, uint32_t *SecureAreaEndAddr, uint32_t Bank)
+{
+ uint32_t regvalue = 0;
+ uint32_t bankBase = 0;
+
+ /* Check Bank parameter value */
+ if(Bank == FLASH_BANK_1)
+ {
+ regvalue = FLASH->SCAR_CUR1;
+ bankBase = FLASH_BANK1_BASE;
+ }
+
+#if defined (DUAL_BANK)
+ if(Bank == FLASH_BANK_2)
+ {
+ regvalue = FLASH->SCAR_CUR2;
+ bankBase = FLASH_BANK2_BASE;
+ }
+#endif /* DUAL_BANK */
+
+ /* Get the secure area settings */
+ (*SecureAreaConfig) = (regvalue & FLASH_SCAR_DMES);
+ (*SecureAreaStartAddr) = ((regvalue & FLASH_SCAR_SEC_AREA_START) << 8) + bankBase;
+ (*SecureAreaEndAddr) = (regvalue & FLASH_SCAR_SEC_AREA_END) >> FLASH_SCAR_SEC_AREA_END_Pos;
+ (*SecureAreaEndAddr) = ((*SecureAreaEndAddr) << 8) + bankBase;
+}
+
+/**
+ * @brief Add a CRC sector to the list of sectors on which the CRC will be calculated
+ * @param Sector Specifies the CRC sector number
+ * @param Bank Specifies the Bank
+ * @retval None
+ */
+static void FLASH_CRC_AddSector(uint32_t Sector, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FLASH_SECTOR(Sector));
+
+ if (Bank == FLASH_BANK_1)
+ {
+ /* Clear CRC sector */
+ FLASH->CRCCR1 &= (~FLASH_CRCCR_CRC_SECT);
+
+ /* Select CRC Sector and activate ADD_SECT bit */
+ FLASH->CRCCR1 |= Sector | FLASH_CRCCR_ADD_SECT;
+ }
+#if defined (DUAL_BANK)
+ else
+ {
+ /* Clear CRC sector */
+ FLASH->CRCCR2 &= (~FLASH_CRCCR_CRC_SECT);
+
+ /* Select CRC Sector and activate ADD_SECT bit */
+ FLASH->CRCCR2 |= Sector | FLASH_CRCCR_ADD_SECT;
+ }
+#endif /* DUAL_BANK */
+}
+
+/**
+ * @brief Select CRC start and end memory addresses on which the CRC will be calculated
+ * @param CRCStartAddr Specifies the CRC start address
+ * @param CRCEndAddr Specifies the CRC end address
+ * @param Bank Specifies the Bank
+ * @retval None
+ */
+static void FLASH_CRC_SelectAddress(uint32_t CRCStartAddr, uint32_t CRCEndAddr, uint32_t Bank)
+{
+ if (Bank == FLASH_BANK_1)
+ {
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK1(CRCStartAddr));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK1(CRCEndAddr));
+
+ /* Write CRC Start and End addresses */
+ FLASH->CRCSADD1 = CRCStartAddr;
+ FLASH->CRCEADD1 = CRCEndAddr;
+ }
+#if defined (DUAL_BANK)
+ else
+ {
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK2(CRCStartAddr));
+ assert_param(IS_FLASH_PROGRAM_ADDRESS_BANK2(CRCEndAddr));
+
+ /* Write CRC Start and End addresses */
+ FLASH->CRCSADD2 = CRCStartAddr;
+ FLASH->CRCEADD2 = CRCEndAddr;
+ }
+#endif /* DUAL_BANK */
+}
+/**
+ * @}
+ */
+
+#if defined (FLASH_OTPBL_LOCKBL)
+/**
+ * @brief Configure the OTP Block Lock.
+ * @param OTP_Block specifies the OTP Block to lock.
+ * This parameter can be a value of @ref FLASHEx_OTP_Blocks
+ * @retval None
+ */
+static void FLASH_OB_OTP_LockConfig(uint32_t OTP_Block)
+{
+ /* Check the parameters */
+ assert_param(IS_OTP_BLOCK(OTP_Block));
+
+ /* Configure the OTP Block lock in the option bytes register */
+ FLASH->OTPBL_PRG |= (OTP_Block & FLASH_OTPBL_LOCKBL);
+}
+
+/**
+ * @brief Get the OTP Block Lock.
+ * @retval OTP_Block specifies the OTP Block to lock.
+ * This return value can be a value of @ref FLASHEx_OTP_Blocks
+ */
+static uint32_t FLASH_OB_OTP_GetLock(void)
+{
+ return (FLASH->OTPBL_CUR);
+}
+#endif /* FLASH_OTPBL_LOCKBL */
+
+#if defined (FLASH_OPTSR2_TCM_AXI_SHARED)
+/**
+ * @brief Configure the TCM / AXI Shared RAM.
+ * @param SharedRamConfig specifies the Shared RAM configuration.
+ * This parameter can be a value of @ref FLASHEx_OB_TCM_AXI_SHARED
+ * @retval None
+ */
+static void FLASH_OB_SharedRAM_Config(uint32_t SharedRamConfig)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_USER_TCM_AXI_SHARED(SharedRamConfig));
+
+ /* Configure the TCM / AXI Shared RAM in the option bytes register */
+ MODIFY_REG(FLASH->OPTSR2_PRG, FLASH_OPTSR2_TCM_AXI_SHARED, SharedRamConfig);
+}
+
+/**
+ * @brief Get the TCM / AXI Shared RAM configuration.
+ * @retval SharedRamConfig returns the TCM / AXI Shared RAM configuration.
+ * This return value can be a value of @ref FLASHEx_OB_TCM_AXI_SHARED
+ */
+static uint32_t FLASH_OB_SharedRAM_GetConfig(void)
+{
+ return (FLASH->OPTSR2_CUR & FLASH_OPTSR2_TCM_AXI_SHARED);
+}
+#endif /* FLASH_OPTSR2_TCM_AXI_SHARED */
+
+#if defined (FLASH_OPTSR2_CPUFREQ_BOOST)
+/**
+ * @brief Configure the CPU Frequency Boost.
+ * @param FreqBoost specifies the CPU Frequency Boost state.
+ * This parameter can be a value of @ref FLASHEx_OB_CPUFREQ_BOOST
+ * @retval None
+ */
+static void FLASH_OB_CPUFreq_BoostConfig(uint32_t FreqBoost)
+{
+ /* Check the parameters */
+ assert_param(IS_OB_USER_CPUFREQ_BOOST(FreqBoost));
+
+ /* Configure the CPU Frequency Boost in the option bytes register */
+ MODIFY_REG(FLASH->OPTSR2_PRG, FLASH_OPTSR2_CPUFREQ_BOOST, FreqBoost);
+}
+
+/**
+ * @brief Get the CPU Frequency Boost state.
+ * @retval FreqBoost returns the CPU Frequency Boost state.
+ * This return value can be a value of @ref FLASHEx_OB_CPUFREQ_BOOST
+ */
+static uint32_t FLASH_OB_CPUFreq_GetBoost(void)
+{
+ return (FLASH->OPTSR2_CUR & FLASH_OPTSR2_CPUFREQ_BOOST);
+}
+#endif /* FLASH_OPTSR2_CPUFREQ_BOOST */
+
+#endif /* HAL_FLASH_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c
new file mode 100755
index 0000000..8044c15
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_gpio.c
@@ -0,0 +1,556 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_gpio.c
+ * @author MCD Application Team
+ * @brief GPIO HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the General Purpose Input/Output (GPIO) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### GPIO Peripheral features #####
+ ==============================================================================
+ [..]
+ (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually
+ configured by software in several modes:
+ (++) Input mode
+ (++) Analog mode
+ (++) Output mode
+ (++) Alternate function mode
+ (++) External interrupt/event lines
+
+ (+) During and just after reset, the alternate functions and external interrupt
+ lines are not active and the I/O ports are configured in input floating mode.
+
+ (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be
+ activated or not.
+
+ (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull
+ type and the IO speed can be selected depending on the VDD value.
+
+ (+) The microcontroller IO pins are connected to onboard peripherals/modules through a
+ multiplexer that allows only one peripheral alternate function (AF) connected
+ to an IO pin at a time. In this way, there can be no conflict between peripherals
+ sharing the same IO pin.
+
+ (+) All ports have external interrupt/event capability. To use external interrupt
+ lines, the port must be configured in input mode. All available GPIO pins are
+ connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
+
+ The external interrupt/event controller consists of up to 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
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup GPIO GPIO
+ * @brief GPIO HAL module driver
+ * @{
+ */
+
+#ifdef HAL_GPIO_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines ------------------------------------------------------------*/
+/** @addtogroup GPIO_Private_Constants GPIO Private Constants
+ * @{
+ */
+
+#if defined(DUAL_CORE)
+#define EXTI_CPU1 (0x01000000U)
+#define EXTI_CPU2 (0x02000000U)
+#endif /*DUAL_CORE*/
+#define GPIO_NUMBER (16U)
+/**
+ * @}
+ */
+/* 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, const GPIO_InitTypeDef *GPIO_Init)
+{
+ uint32_t position = 0x00U;
+ uint32_t iocurrent;
+ uint32_t temp;
+ EXTI_Core_TypeDef *EXTI_CurrentCPU;
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ EXTI_CurrentCPU = EXTI_D2; /* EXTI for CM4 CPU */
+#else
+ EXTI_CurrentCPU = EXTI_D1; /* EXTI for CM7 CPU */
+#endif
+
+ /* 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));
+
+ /* Configure the port pins */
+ while (((GPIO_Init->Pin) >> position) != 0x00U)
+ {
+ /* Get current io position */
+ iocurrent = (GPIO_Init->Pin) & (1UL << position);
+
+ if (iocurrent != 0x00U)
+ {
+ /*--------------------- GPIO Mode Configuration ------------------------*/
+ /* In case of Output or Alternate function mode selection */
+ if (((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) || ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF))
+ {
+ /* Check the Speed parameter */
+ assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
+
+ /* Configure the IO Speed */
+ temp = GPIOx->OSPEEDR;
+ temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2U));
+ temp |= (GPIO_Init->Speed << (position * 2U));
+ GPIOx->OSPEEDR = temp;
+
+ /* Configure the IO Output Type */
+ temp = GPIOx->OTYPER;
+ temp &= ~(GPIO_OTYPER_OT0 << position) ;
+ temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
+ GPIOx->OTYPER = temp;
+ }
+
+ if (((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG) ||
+ (((GPIO_Init->Mode & GPIO_MODE) == MODE_ANALOG) && (GPIO_Init->Pull != GPIO_PULLUP)))
+ {
+ /* Check the Pull parameter */
+ assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
+
+ /* Activate the Pull-up or Pull down resistor for the current IO */
+ temp = GPIOx->PUPDR;
+ temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
+ temp |= ((GPIO_Init->Pull) << (position * 2U));
+ GPIOx->PUPDR = temp;
+ }
+
+ /* In case of Alternate function mode selection */
+ if ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
+ {
+ /* Check the Alternate function parameters */
+ assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
+
+ /* Configure Alternate function mapped with the current IO */
+ temp = GPIOx->AFR[position >> 3U];
+ temp &= ~(0xFUL << ((position & 0x07U) * 4U));
+ temp |= ((GPIO_Init->Alternate) << ((position & 0x07U) * 4U));
+ GPIOx->AFR[position >> 3U] = temp;
+ }
+
+ /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
+ temp = GPIOx->MODER;
+ temp &= ~(GPIO_MODER_MODE0 << (position * 2U));
+ temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2U));
+ GPIOx->MODER = temp;
+
+ /*--------------------- EXTI Mode Configuration ------------------------*/
+ /* Configure the External Interrupt or event for the current IO */
+ if ((GPIO_Init->Mode & EXTI_MODE) != 0x00U)
+ {
+ /* Enable SYSCFG Clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ temp = SYSCFG->EXTICR[position >> 2U];
+ temp &= ~(0x0FUL << (4U * (position & 0x03U)));
+ temp |= (GPIO_GET_INDEX(GPIOx) << (4U * (position & 0x03U)));
+ SYSCFG->EXTICR[position >> 2U] = temp;
+
+ /* Clear Rising Falling edge configuration */
+ temp = EXTI->RTSR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & TRIGGER_RISING) != 0x00U)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->RTSR1 = temp;
+
+ temp = EXTI->FTSR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00U)
+ {
+ temp |= iocurrent;
+ }
+ EXTI->FTSR1 = temp;
+
+ temp = EXTI_CurrentCPU->EMR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & EXTI_EVT) != 0x00U)
+ {
+ temp |= iocurrent;
+ }
+ EXTI_CurrentCPU->EMR1 = temp;
+
+ /* Clear EXTI line configuration */
+ temp = EXTI_CurrentCPU->IMR1;
+ temp &= ~(iocurrent);
+ if ((GPIO_Init->Mode & EXTI_IT) != 0x00U)
+ {
+ temp |= iocurrent;
+ }
+ EXTI_CurrentCPU->IMR1 = temp;
+ }
+ }
+
+ position++;
+ }
+}
+
+/**
+ * @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 = 0x00U;
+ uint32_t iocurrent;
+ uint32_t tmp;
+ EXTI_Core_TypeDef *EXTI_CurrentCPU;
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ EXTI_CurrentCPU = EXTI_D2; /* EXTI for CM4 CPU */
+#else
+ EXTI_CurrentCPU = EXTI_D1; /* EXTI for CM7 CPU */
+#endif
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* Configure the port pins */
+ while ((GPIO_Pin >> position) != 0x00U)
+ {
+ /* Get current io position */
+ iocurrent = GPIO_Pin & (1UL << position) ;
+
+ if (iocurrent != 0x00U)
+ {
+ /*------------------------- EXTI Mode Configuration --------------------*/
+ /* Clear the External Interrupt or Event for the current IO */
+ tmp = SYSCFG->EXTICR[position >> 2U];
+ tmp &= (0x0FUL << (4U * (position & 0x03U)));
+ if (tmp == (GPIO_GET_INDEX(GPIOx) << (4U * (position & 0x03U))))
+ {
+ /* Clear EXTI line configuration for Current CPU */
+ EXTI_CurrentCPU->IMR1 &= ~(iocurrent);
+ EXTI_CurrentCPU->EMR1 &= ~(iocurrent);
+
+ /* Clear Rising Falling edge configuration */
+ EXTI->FTSR1 &= ~(iocurrent);
+ EXTI->RTSR1 &= ~(iocurrent);
+
+ tmp = 0x0FUL << (4U * (position & 0x03U));
+ SYSCFG->EXTICR[position >> 2U] &= ~tmp;
+ }
+
+ /*------------------------- GPIO Mode Configuration --------------------*/
+ /* Configure IO in Analog Mode */
+ GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2U));
+
+ /* Configure the default Alternate Function in current IO */
+ GPIOx->AFR[position >> 3U] &= ~(0xFUL << ((position & 0x07U) * 4U)) ;
+
+ /* Deactivate the Pull-up and Pull-down resistor for the current IO */
+ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
+
+ /* Configure the default value IO Output Type */
+ GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ;
+
+ /* Configure the default value for IO Speed */
+ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2U));
+ }
+
+ position++;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
+ * @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
+ *
+@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(const GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
+{
+ GPIO_PinState bitstatus;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ if ((GPIOx->IDR & GPIO_Pin) != 0x00U)
+ {
+ bitstatus = GPIO_PIN_SET;
+ }
+ else
+ {
+ bitstatus = GPIO_PIN_RESET;
+ }
+ return bitstatus;
+}
+
+/**
+ * @brief 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 << GPIO_NUMBER;
+ }
+}
+
+/**
+ * @brief Toggles the specified GPIO pins.
+ * @param GPIOx: Where x can be (A..K) 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)
+{
+ uint32_t odr;
+
+ /* Check the parameters */
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* get current Output Data Register value */
+ odr = GPIOx->ODR;
+
+ /* Set selected pins that were at low level, and reset ones that were high */
+ GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
+}
+
+/**
+ * @brief 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..K) to select the GPIO peripheral for STM32H7 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_LOCK_INSTANCE(GPIOx));
+ assert_param(IS_GPIO_PIN(GPIO_Pin));
+
+ /* Apply lock key write sequence */
+ tmp |= GPIO_Pin;
+ /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
+ GPIOx->LCKR = tmp;
+ /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
+ GPIOx->LCKR = GPIO_Pin;
+ /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
+ GPIOx->LCKR = tmp;
+ /* Read LCKK register. This read is mandatory to complete key lock sequence*/
+ tmp = GPIOx->LCKR;
+
+ /* read again in order to confirm lock is active */
+ if ((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00U)
+ {
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Handle EXTI interrupt request.
+ * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
+ * @retval None
+ */
+void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
+{
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ if (__HAL_GPIO_EXTID2_GET_IT(GPIO_Pin) != 0x00U)
+ {
+ __HAL_GPIO_EXTID2_CLEAR_IT(GPIO_Pin);
+ HAL_GPIO_EXTI_Callback(GPIO_Pin);
+ }
+#else
+ /* EXTI line interrupt detected */
+ if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00U)
+ {
+ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
+ HAL_GPIO_EXTI_Callback(GPIO_Pin);
+ }
+#endif
+}
+
+/**
+ * @brief EXTI line detection callback.
+ * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
+ * @retval None
+ */
+__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(GPIO_Pin);
+
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_GPIO_EXTI_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_GPIO_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c
new file mode 100755
index 0000000..01a01c2
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_hsem.c
@@ -0,0 +1,447 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_hsem.c
+ * @author MCD Application Team
+ * @brief HSEM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the semaphore peripheral:
+ * + Semaphore Take function (2-Step Procedure) , non blocking
+ * + Semaphore FastTake function (1-Step Procedure) , non blocking
+ * + Semaphore Status check
+ * + Semaphore Clear Key Set and Get
+ * + Release and release all functions
+ * + Semaphore notification enabling and disabling and callnack functions
+ * + IRQ handler management
+ *
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#)Take a semaphore In 2-Step mode Using function HAL_HSEM_Take. This function takes as parameters :
+ (++) the semaphore ID from 0 to 31
+ (++) the process ID from 0 to 255
+ (#) Fast Take semaphore In 1-Step mode Using function HAL_HSEM_FastTake. This function takes as parameter :
+ (++) the semaphore ID from 0_ID to 31. Note that the process ID value is implicitly assumed as zero
+ (#) Check if a semaphore is Taken using function HAL_HSEM_IsSemTaken. This function takes as parameter :
+ (++) the semaphore ID from 0_ID to 31
+ (++) It returns 1 if the given semaphore is taken otherwise (Free) zero
+ (#)Release a semaphore using function with HAL_HSEM_Release. This function takes as parameters :
+ (++) the semaphore ID from 0 to 31
+ (++) the process ID from 0 to 255:
+ (++) Note: If ProcessID and MasterID match, semaphore is freed, and an interrupt
+ may be generated when enabled (notification activated). If ProcessID or MasterID does not match,
+ semaphore remains taken (locked)
+
+ (#)Release all semaphores at once taken by a given Master using function HAL_HSEM_Release_All
+ This function takes as parameters :
+ (++) the Release Key (value from 0 to 0xFFFF) can be Set or Get respectively by
+ HAL_HSEM_SetClearKey() or HAL_HSEM_GetClearKey functions
+ (++) the Master ID:
+ (++) Note: If the Key and MasterID match, all semaphores taken by the given CPU that corresponds
+ to MasterID will be freed, and an interrupt may be generated when enabled (notification activated). If the
+ Key or the MasterID doesn't match, semaphores remains taken (locked)
+
+ (#)Semaphores Release all key functions:
+ (++) HAL_HSEM_SetClearKey() to set semaphore release all Key
+ (++) HAL_HSEM_GetClearKey() to get release all Key
+ (#)Semaphores notification functions :
+ (++) HAL_HSEM_ActivateNotification to activate a notification callback on
+ a given semaphores Mask (bitfield). When one or more semaphores defined by the mask are released
+ the callback HAL_HSEM_FreeCallback will be asserted giving as parameters a mask of the released
+ semaphores (bitfield).
+
+ (++) HAL_HSEM_DeactivateNotification to deactivate the notification of a given semaphores Mask (bitfield).
+ (++) See the description of the macro __HAL_HSEM_SEMID_TO_MASK to check how to calculate a semaphore mask
+ Used by the notification functions
+ *** HSEM HAL driver macros list ***
+ =============================================
+ [..] Below the list of most used macros in HSEM HAL driver.
+
+ (+) __HAL_HSEM_SEMID_TO_MASK: Helper macro to convert a Semaphore ID to a Mask.
+ [..] Example of use :
+ [..] mask = __HAL_HSEM_SEMID_TO_MASK(8) | __HAL_HSEM_SEMID_TO_MASK(21) | __HAL_HSEM_SEMID_TO_MASK(25).
+ [..] All next macros take as parameter a semaphore Mask (bitfiled) that can be constructed using __HAL_HSEM_SEMID_TO_MASK as the above example.
+ (+) __HAL_HSEM_ENABLE_IT: Enable the specified semaphores Mask interrupts.
+ (+) __HAL_HSEM_DISABLE_IT: Disable the specified semaphores Mask interrupts.
+ (+) __HAL_HSEM_GET_IT: Checks whether the specified semaphore interrupt has occurred or not.
+ (+) __HAL_HSEM_GET_FLAG: Get the semaphores status release flags.
+ (+) __HAL_HSEM_CLEAR_FLAG: Clear the semaphores status release flags.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup HSEM HSEM
+ * @brief HSEM HAL module driver
+ * @{
+ */
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#if defined(DUAL_CORE)
+/** @defgroup HSEM_Private_Constants HSEM Private Constants
+ * @{
+ */
+
+#ifndef HSEM_R_MASTERID
+#define HSEM_R_MASTERID HSEM_R_COREID
+#endif
+
+#ifndef HSEM_RLR_MASTERID
+#define HSEM_RLR_MASTERID HSEM_RLR_COREID
+#endif
+
+#ifndef HSEM_CR_MASTERID
+#define HSEM_CR_MASTERID HSEM_CR_COREID
+#endif
+
+/**
+ * @}
+ */
+#endif /* DUAL_CORE */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup HSEM_Exported_Functions HSEM Exported Functions
+ * @{
+ */
+
+/** @defgroup HSEM_Exported_Functions_Group1 Take and Release functions
+ * @brief HSEM Take and Release functions
+ *
+@verbatim
+ ==============================================================================
+ ##### HSEM Take and Release functions #####
+ ==============================================================================
+[..] This section provides functions allowing to:
+ (+) Take a semaphore with 2 Step method
+ (+) Fast Take a semaphore with 1 Step method
+ (+) Check semaphore state Taken or not
+ (+) Release a semaphore
+ (+) Release all semaphore at once
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Take a semaphore in 2 Step mode.
+ * @param SemID: semaphore ID from 0 to 31
+ * @param ProcessID: Process ID from 0 to 255
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HSEM_Take(uint32_t SemID, uint32_t ProcessID)
+{
+ /* Check the parameters */
+ assert_param(IS_HSEM_SEMID(SemID));
+ assert_param(IS_HSEM_PROCESSID(ProcessID));
+
+#if USE_MULTI_CORE_SHARED_CODE != 0U
+ /* First step write R register with MasterID, processID and take bit=1*/
+ HSEM->R[SemID] = ((ProcessID & HSEM_R_PROCID) | ((HAL_GetCurrentCPUID() << POSITION_VAL(HSEM_R_MASTERID)) & HSEM_R_MASTERID) | HSEM_R_LOCK);
+
+ /* second step : read the R register . Take achieved if MasterID and processID match and take bit set to 1 */
+ if (HSEM->R[SemID] == ((ProcessID & HSEM_R_PROCID) | ((HAL_GetCurrentCPUID() << POSITION_VAL(HSEM_R_MASTERID)) & HSEM_R_MASTERID) | HSEM_R_LOCK))
+ {
+ /*take success when MasterID and ProcessID match and take bit set*/
+ return HAL_OK;
+ }
+#else
+ /* First step write R register with MasterID, processID and take bit=1*/
+ HSEM->R[SemID] = (ProcessID | HSEM_CR_COREID_CURRENT | HSEM_R_LOCK);
+
+ /* second step : read the R register . Take achieved if MasterID and processID match and take bit set to 1 */
+ if (HSEM->R[SemID] == (ProcessID | HSEM_CR_COREID_CURRENT | HSEM_R_LOCK))
+ {
+ /*take success when MasterID and ProcessID match and take bit set*/
+ return HAL_OK;
+ }
+#endif
+
+ /* Semaphore take fails*/
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Fast Take a semaphore with 1 Step mode.
+ * @param SemID: semaphore ID from 0 to 31
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_HSEM_FastTake(uint32_t SemID)
+{
+ /* Check the parameters */
+ assert_param(IS_HSEM_SEMID(SemID));
+
+#if USE_MULTI_CORE_SHARED_CODE != 0U
+ /* Read the RLR register to take the semaphore */
+ if (HSEM->RLR[SemID] == (((HAL_GetCurrentCPUID() << POSITION_VAL(HSEM_R_MASTERID)) & HSEM_RLR_MASTERID) | HSEM_RLR_LOCK))
+ {
+ /*take success when MasterID match and take bit set*/
+ return HAL_OK;
+ }
+#else
+ /* Read the RLR register to take the semaphore */
+ if (HSEM->RLR[SemID] == (HSEM_CR_COREID_CURRENT | HSEM_RLR_LOCK))
+ {
+ /*take success when MasterID match and take bit set*/
+ return HAL_OK;
+ }
+#endif
+
+ /* Semaphore take fails */
+ return HAL_ERROR;
+}
+/**
+ * @brief Check semaphore state Taken or not.
+ * @param SemID: semaphore ID
+ * @retval HAL HSEM state
+ */
+uint32_t HAL_HSEM_IsSemTaken(uint32_t SemID)
+{
+ return (((HSEM->R[SemID] & HSEM_R_LOCK) != 0U) ? 1UL : 0UL);
+}
+
+
+/**
+ * @brief Release a semaphore.
+ * @param SemID: semaphore ID from 0 to 31
+ * @param ProcessID: Process ID from 0 to 255
+ * @retval None
+ */
+void HAL_HSEM_Release(uint32_t SemID, uint32_t ProcessID)
+{
+ /* Check the parameters */
+ assert_param(IS_HSEM_SEMID(SemID));
+ assert_param(IS_HSEM_PROCESSID(ProcessID));
+
+ /* Clear the semaphore by writing to the R register : the MasterID , the processID and take bit = 0 */
+#if USE_MULTI_CORE_SHARED_CODE != 0U
+ HSEM->R[SemID] = (ProcessID | ((HAL_GetCurrentCPUID() << POSITION_VAL(HSEM_R_MASTERID)) & HSEM_R_MASTERID));
+#else
+ HSEM->R[SemID] = (ProcessID | HSEM_CR_COREID_CURRENT);
+#endif
+
+}
+
+/**
+ * @brief Release All semaphore used by a given Master .
+ * @param Key: Semaphore Key , value from 0 to 0xFFFF
+ * @param CoreID: CoreID of the CPU that is using semaphores to be released
+ * @retval None
+ */
+void HAL_HSEM_ReleaseAll(uint32_t Key, uint32_t CoreID)
+{
+ assert_param(IS_HSEM_KEY(Key));
+ assert_param(IS_HSEM_COREID(CoreID));
+
+ HSEM->CR = ((Key << HSEM_CR_KEY_Pos) | (CoreID << HSEM_CR_COREID_Pos));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HSEM_Exported_Functions_Group2 HSEM Set and Get Key functions
+ * @brief HSEM Set and Get Key functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### HSEM Set and Get Key functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to:
+ (+) Set semaphore Key
+ (+) Get semaphore Key
+@endverbatim
+
+ * @{
+ */
+
+/**
+ * @brief Set semaphore Key .
+ * @param Key: Semaphore Key , value from 0 to 0xFFFF
+ * @retval None
+ */
+void HAL_HSEM_SetClearKey(uint32_t Key)
+{
+ assert_param(IS_HSEM_KEY(Key));
+
+ MODIFY_REG(HSEM->KEYR, HSEM_KEYR_KEY, (Key << HSEM_KEYR_KEY_Pos));
+
+}
+
+/**
+ * @brief Get semaphore Key .
+ * @retval Semaphore Key , value from 0 to 0xFFFF
+ */
+uint32_t HAL_HSEM_GetClearKey(void)
+{
+ return (HSEM->KEYR >> HSEM_KEYR_KEY_Pos);
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HSEM_Exported_Functions_Group3 HSEM IRQ handler management
+ * @brief HSEM Notification functions.
+ *
+@verbatim
+ ==============================================================================
+ ##### HSEM IRQ handler management and Notification functions #####
+ ==============================================================================
+[..] This section provides HSEM IRQ handler and Notification function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Activate Semaphore release Notification for a given Semaphores Mask .
+ * @param SemMask: Mask of Released semaphores
+ * @retval Semaphore Key
+ */
+void HAL_HSEM_ActivateNotification(uint32_t SemMask)
+{
+#if USE_MULTI_CORE_SHARED_CODE != 0U
+ /*enable the semaphore mask interrupts */
+ if (HAL_GetCurrentCPUID() == HSEM_CPU1_COREID)
+ {
+ /*Use interrupt line 0 for CPU1 Master */
+ HSEM->C1IER |= SemMask;
+ }
+ else /* HSEM_CPU2_COREID */
+ {
+ /*Use interrupt line 1 for CPU2 Master*/
+ HSEM->C2IER |= SemMask;
+ }
+#else
+ HSEM_COMMON->IER |= SemMask;
+#endif
+}
+
+/**
+ * @brief Deactivate Semaphore release Notification for a given Semaphores Mask .
+ * @param SemMask: Mask of Released semaphores
+ * @retval Semaphore Key
+ */
+void HAL_HSEM_DeactivateNotification(uint32_t SemMask)
+{
+#if USE_MULTI_CORE_SHARED_CODE != 0U
+ /*enable the semaphore mask interrupts */
+ if (HAL_GetCurrentCPUID() == HSEM_CPU1_COREID)
+ {
+ /*Use interrupt line 0 for CPU1 Master */
+ HSEM->C1IER &= ~SemMask;
+ }
+ else /* HSEM_CPU2_COREID */
+ {
+ /*Use interrupt line 1 for CPU2 Master*/
+ HSEM->C2IER &= ~SemMask;
+ }
+#else
+ HSEM_COMMON->IER &= ~SemMask;
+#endif
+}
+
+/**
+ * @brief This function handles HSEM interrupt request
+ * @retval None
+ */
+void HAL_HSEM_IRQHandler(void)
+{
+ uint32_t statusreg;
+#if USE_MULTI_CORE_SHARED_CODE != 0U
+ if (HAL_GetCurrentCPUID() == HSEM_CPU1_COREID)
+ {
+ /* Get the list of masked freed semaphores*/
+ statusreg = HSEM->C1MISR; /*Use interrupt line 0 for CPU1 Master*/
+
+ /*Disable Interrupts*/
+ HSEM->C1IER &= ~((uint32_t)statusreg);
+
+ /*Clear Flags*/
+ HSEM->C1ICR = ((uint32_t)statusreg);
+ }
+ else /* HSEM_CPU2_COREID */
+ {
+ /* Get the list of masked freed semaphores*/
+ statusreg = HSEM->C2MISR;/*Use interrupt line 1 for CPU2 Master*/
+
+ /*Disable Interrupts*/
+ HSEM->C2IER &= ~((uint32_t)statusreg);
+
+ /*Clear Flags*/
+ HSEM->C2ICR = ((uint32_t)statusreg);
+ }
+#else
+ /* Get the list of masked freed semaphores*/
+ statusreg = HSEM_COMMON->MISR;
+
+ /*Disable Interrupts*/
+ HSEM_COMMON->IER &= ~((uint32_t)statusreg);
+
+ /*Clear Flags*/
+ HSEM_COMMON->ICR = ((uint32_t)statusreg);
+
+#endif
+ /* Call FreeCallback */
+ HAL_HSEM_FreeCallback(statusreg);
+}
+
+/**
+ * @brief Semaphore Released Callback.
+ * @param SemMask: Mask of Released semaphores
+ * @retval None
+ */
+__weak void HAL_HSEM_FreeCallback(uint32_t SemMask)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(SemMask);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_HSEM_FreeCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_HSEM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c
new file mode 100755
index 0000000..56cae08
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c.c
@@ -0,0 +1,7528 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_i2c.c
+ * @author MCD Application Team
+ * @brief I2C HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Inter Integrated Circuit (I2C) peripheral:
+ * + Initialization and de-initialization functions
+ * + IO operation functions
+ * + Peripheral State and Errors functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The I2C HAL driver can be used as follows:
+
+ (#) Declare a I2C_HandleTypeDef handle structure, for example:
+ I2C_HandleTypeDef hi2c;
+
+ (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API:
+ (##) Enable the I2Cx interface clock
+ (##) I2C pins configuration
+ (+++) Enable the clock for the I2C GPIOs
+ (+++) Configure I2C pins as alternate function open-drain
+ (##) NVIC configuration if you need to use interrupt process
+ (+++) Configure the I2Cx interrupt priority
+ (+++) Enable the NVIC I2C IRQ Channel
+ (##) DMA Configuration if you need to use DMA process
+ (+++) Declare a DMA_HandleTypeDef handle structure for
+ the transmit or receive stream or channel depends on Instance
+ (+++) Enable the DMAx interface clock using
+ (+++) Configure the DMA handle parameters
+ (+++) Configure the DMA Tx or Rx stream or channel depends on Instance
+ (+++) 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 or channel depends on Instance
+
+ (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode,
+ Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure.
+
+ (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware
+ (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API.
+
+ (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady()
+
+ (#) For I2C IO and IO MEM operations, three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit()
+ (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive()
+ (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit()
+ (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive()
+
+ *** Polling mode IO MEM operation ***
+ =====================================
+ [..]
+ (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write()
+ (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read()
+
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT()
+ (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Receive_IT()
+ (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Transmit_IT()
+ (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Receive_IT()
+ (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (+) Abort a master or memory I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_AbortCpltCallback()
+ (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro.
+ This action will inform Master to generate a Stop condition to discard the communication.
+
+
+ *** Interrupt mode or DMA mode IO sequential operation ***
+ ==========================================================
+ [..]
+ (@) These interfaces allow to manage a sequential transfer with a repeated start condition
+ when a direction change during transfer
+ [..]
+ (+) A specific option field manage the different steps of a sequential transfer
+ (+) Option field values are defined through I2C_XFEROPTIONS and are listed below:
+ (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functional is same as associated interfaces in
+ no sequential mode
+ (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address
+ and data to transfer without a final stop condition
+ (++) I2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with
+ start condition, address and data to transfer without a final stop condition,
+ an then permit a call the same master sequential interface several times
+ (like HAL_I2C_Master_Seq_Transmit_IT() then HAL_I2C_Master_Seq_Transmit_IT()
+ or HAL_I2C_Master_Seq_Transmit_DMA() then HAL_I2C_Master_Seq_Transmit_DMA())
+ (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address
+ and with new data to transfer if the direction change or manage only the new data to
+ transfer
+ if no direction change and without a final stop condition in both cases
+ (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address
+ and with new data to transfer if the direction change or manage only the new data to
+ transfer
+ if no direction change and with a final stop condition in both cases
+ (++) I2C_LAST_FRAME_NO_STOP: Sequential usage (Master only), this option allow to manage a restart condition
+ after several call of the same master sequential interface several times
+ (link with option I2C_FIRST_AND_NEXT_FRAME).
+ Usage can, transfer several bytes one by one using
+ HAL_I2C_Master_Seq_Transmit_IT
+ or HAL_I2C_Master_Seq_Receive_IT
+ or HAL_I2C_Master_Seq_Transmit_DMA
+ or HAL_I2C_Master_Seq_Receive_DMA
+ with option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME.
+ Then usage of this option I2C_LAST_FRAME_NO_STOP at the last Transmit or
+ Receive sequence permit to call the opposite interface Receive or Transmit
+ without stopping the communication and so generate a restart condition.
+ (++) I2C_OTHER_FRAME: Sequential usage (Master only), this option allow to manage a restart condition after
+ each call of the same master sequential
+ interface.
+ Usage can, transfer several bytes one by one with a restart with slave address between
+ each bytes using
+ HAL_I2C_Master_Seq_Transmit_IT
+ or HAL_I2C_Master_Seq_Receive_IT
+ or HAL_I2C_Master_Seq_Transmit_DMA
+ or HAL_I2C_Master_Seq_Receive_DMA
+ with option I2C_FIRST_FRAME then I2C_OTHER_FRAME.
+ Then usage of this option I2C_OTHER_AND_LAST_FRAME at the last frame to help automatic
+ generation of STOP condition.
+
+ (+) Different sequential I2C interfaces are listed below:
+ (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Master_Seq_Transmit_IT() or using HAL_I2C_Master_Seq_Transmit_DMA()
+ (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and
+ users can add their own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Master_Seq_Receive_IT() or using HAL_I2C_Master_Seq_Receive_DMA()
+ (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (++) Abort a master or memory IT or DMA I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_AbortCpltCallback()
+ (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT()
+ HAL_I2C_DisableListen_IT()
+ (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and users can
+ add their own code to check the Address Match Code and the transmission direction request by master
+ (Write/Read).
+ (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ListenCpltCallback()
+ (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Slave_Seq_Transmit_IT() or using HAL_I2C_Slave_Seq_Transmit_DMA()
+ (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and
+ users can add their own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using
+ HAL_I2C_Slave_Seq_Receive_IT() or using HAL_I2C_Slave_Seq_Receive_DMA()
+ (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (++) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro.
+ This action will inform Master to generate a Stop condition to discard the communication.
+
+ *** Interrupt mode IO MEM operation ***
+ =======================================
+ [..]
+ (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using
+ HAL_I2C_Mem_Write_IT()
+ (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using
+ HAL_I2C_Mem_Read_IT()
+ (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ ==============================
+ [..]
+ (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Master_Transmit_DMA()
+ (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterTxCpltCallback()
+ (+) Receive in master mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Master_Receive_DMA()
+ (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MasterRxCpltCallback()
+ (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Slave_Transmit_DMA()
+ (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback()
+ (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using
+ HAL_I2C_Slave_Receive_DMA()
+ (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+ (+) Abort a master or memory I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT()
+ (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_AbortCpltCallback()
+ (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro.
+ This action will inform Master to generate a Stop condition to discard the communication.
+
+ *** DMA mode IO MEM operation ***
+ =================================
+ [..]
+ (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using
+ HAL_I2C_Mem_Write_DMA()
+ (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemTxCpltCallback()
+ (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using
+ HAL_I2C_Mem_Read_DMA()
+ (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and users can
+ add their own code by customization of function pointer HAL_I2C_MemRxCpltCallback()
+ (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and users can
+ add their own code by customization of function pointer HAL_I2C_ErrorCallback()
+
+
+ *** I2C HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in I2C HAL driver.
+
+ (+) __HAL_I2C_ENABLE: Enable the I2C peripheral
+ (+) __HAL_I2C_DISABLE: Disable the I2C peripheral
+ (+) __HAL_I2C_GENERATE_NACK: Generate a Non-Acknowledge I2C peripheral in Slave mode
+ (+) __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not
+ (+) __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag
+ (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt
+ (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation flag USE_HAL_I2C_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use Functions HAL_I2C_RegisterCallback() or HAL_I2C_RegisterAddrCallback()
+ to register an interrupt callback.
+ [..]
+ Function HAL_I2C_RegisterCallback() allows to register following callbacks:
+ (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
+ (+) MasterRxCpltCallback : callback for Master reception end of transfer.
+ (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer.
+ (+) SlaveRxCpltCallback : callback for Slave reception end of transfer.
+ (+) ListenCpltCallback : callback for end of listen mode.
+ (+) MemTxCpltCallback : callback for Memory transmission end of transfer.
+ (+) MemRxCpltCallback : callback for Memory reception end of transfer.
+ (+) ErrorCallback : callback for error detection.
+ (+) AbortCpltCallback : callback for abort completion process.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+ [..]
+ For specific callback AddrCallback use dedicated register callbacks : HAL_I2C_RegisterAddrCallback().
+ [..]
+ Use function HAL_I2C_UnRegisterCallback to reset a callback to the default
+ weak function.
+ HAL_I2C_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+ This function allows to reset following callbacks:
+ (+) MasterTxCpltCallback : callback for Master transmission end of transfer.
+ (+) MasterRxCpltCallback : callback for Master reception end of transfer.
+ (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer.
+ (+) SlaveRxCpltCallback : callback for Slave reception end of transfer.
+ (+) ListenCpltCallback : callback for end of listen mode.
+ (+) MemTxCpltCallback : callback for Memory transmission end of transfer.
+ (+) MemRxCpltCallback : callback for Memory reception end of transfer.
+ (+) ErrorCallback : callback for error detection.
+ (+) AbortCpltCallback : callback for abort completion process.
+ (+) MspInitCallback : callback for Msp Init.
+ (+) MspDeInitCallback : callback for Msp DeInit.
+ [..]
+ For callback AddrCallback use dedicated register callbacks : HAL_I2C_UnRegisterAddrCallback().
+ [..]
+ By default, after the HAL_I2C_Init() and when the state is HAL_I2C_STATE_RESET
+ all callbacks are set to the corresponding weak functions:
+ examples HAL_I2C_MasterTxCpltCallback(), HAL_I2C_MasterRxCpltCallback().
+ Exception done for MspInit and MspDeInit functions that are
+ reset to the legacy weak functions in the HAL_I2C_Init()/ HAL_I2C_DeInit() only when
+ these callbacks are null (not registered beforehand).
+ If MspInit or MspDeInit are not null, the HAL_I2C_Init()/ HAL_I2C_DeInit()
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
+ [..]
+ Callbacks can be registered/unregistered in HAL_I2C_STATE_READY state only.
+ Exception done MspInit/MspDeInit functions that can be registered/unregistered
+ in HAL_I2C_STATE_READY or HAL_I2C_STATE_RESET state,
+ thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
+ Then, the user first registers the MspInit/MspDeInit user callbacks
+ using HAL_I2C_RegisterCallback() before calling HAL_I2C_DeInit()
+ or HAL_I2C_Init() function.
+ [..]
+ When the compilation flag USE_HAL_I2C_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all callbacks
+ are set to the corresponding weak functions.
+
+ [..]
+ (@) You can refer to the I2C HAL driver header file for more useful macros
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2C I2C
+ * @brief I2C HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup I2C_Private_Define I2C Private Define
+ * @{
+ */
+#define TIMING_CLEAR_MASK (0xF0FFFFFFU) /*!< I2C TIMING clear register Mask */
+#define I2C_TIMEOUT_ADDR (10000U) /*!< 10 s */
+#define I2C_TIMEOUT_BUSY (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_DIR (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_RXNE (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_STOPF (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_TC (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_TCR (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_TXIS (25U) /*!< 25 ms */
+#define I2C_TIMEOUT_FLAG (25U) /*!< 25 ms */
+
+#define MAX_NBYTE_SIZE 255U
+#define SLAVE_ADDR_SHIFT 7U
+#define SLAVE_ADDR_MSK 0x06U
+
+/* Private define for @ref PreviousState usage */
+#define I2C_STATE_MSK ((uint32_t)((uint32_t)((uint32_t)HAL_I2C_STATE_BUSY_TX | \
+ (uint32_t)HAL_I2C_STATE_BUSY_RX) & \
+ (uint32_t)(~((uint32_t)HAL_I2C_STATE_READY))))
+/*!< Mask State define, keep only RX and TX bits */
+#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE))
+/*!< Default Value */
+#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MASTER))
+/*!< Master Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MASTER))
+/*!< Master Busy RX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_SLAVE))
+/*!< Slave Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_SLAVE))
+/*!< Slave Busy RX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MEM_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MEM))
+/*!< Memory Busy TX, combinaison of State LSB and Mode enum */
+#define I2C_STATE_MEM_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | \
+ (uint32_t)HAL_I2C_MODE_MEM))
+/*!< Memory Busy RX, combinaison of State LSB and Mode enum */
+
+
+/* Private define to centralize the enable/disable of Interrupts */
+#define I2C_XFER_TX_IT (uint16_t)(0x0001U) /*!< Bit field can be combinated with
+ @ref I2C_XFER_LISTEN_IT */
+#define I2C_XFER_RX_IT (uint16_t)(0x0002U) /*!< Bit field can be combinated with
+ @ref I2C_XFER_LISTEN_IT */
+#define I2C_XFER_LISTEN_IT (uint16_t)(0x8000U) /*!< Bit field can be combinated with @ref I2C_XFER_TX_IT
+ and @ref I2C_XFER_RX_IT */
+
+#define I2C_XFER_ERROR_IT (uint16_t)(0x0010U) /*!< Bit definition to manage addition of global Error
+ and NACK treatment */
+#define I2C_XFER_CPLT_IT (uint16_t)(0x0020U) /*!< Bit definition to manage only STOP evenement */
+#define I2C_XFER_RELOAD_IT (uint16_t)(0x0040U) /*!< Bit definition to manage only Reload of NBYTE */
+
+/* Private define Sequential Transfer Options default/reset value */
+#define I2C_NO_OPTION_FRAME (0xFFFF0000U)
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @addtogroup I2C_Private_Macro
+ * @{
+ */
+/* Macro to get remaining data to transfer on DMA side */
+#define I2C_GET_DMA_REMAIN_DATA(__HANDLE__) __HAL_DMA_GET_COUNTER(__HANDLE__)
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+
+/** @defgroup I2C_Private_Functions I2C Private Functions
+ * @{
+ */
+/* Private functions to handle DMA transfer */
+static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma);
+static void I2C_DMAError(DMA_HandleTypeDef *hdma);
+static void I2C_DMAAbort(DMA_HandleTypeDef *hdma);
+
+
+/* Private functions to handle IT transfer */
+static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITMasterSeqCplt(I2C_HandleTypeDef *hi2c);
+static void I2C_ITSlaveSeqCplt(I2C_HandleTypeDef *hi2c);
+static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags);
+static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode);
+
+/* Private functions to handle IT transfer */
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart);
+
+/* Private functions for I2C transfer IRQ handler */
+static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Mem_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Mem_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources);
+
+/* Private functions to handle flags during polling transfer */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status,
+ uint32_t Timeout, uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+static HAL_StatusTypeDef I2C_IsErrorOccurred(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart);
+
+/* Private functions to centralize the enable/disable of Interrupts */
+static void I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest);
+static void I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest);
+
+/* Private function to treat different error callback */
+static void I2C_TreatErrorCallback(I2C_HandleTypeDef *hi2c);
+
+/* Private function to flush TXDR register */
+static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c);
+
+/* Private function to handle start, restart or stop a transfer */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
+ uint32_t Request);
+
+/* Private function to Convert Specific options */
+static void I2C_ConvertOtherXferOptions(I2C_HandleTypeDef *hi2c);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup I2C_Exported_Functions I2C Exported Functions
+ * @{
+ */
+
+/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This subsection provides a set of functions allowing to initialize and
+ deinitialize the I2Cx peripheral:
+
+ (+) User must Implement HAL_I2C_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_I2C_Init() to configure the selected device with
+ the selected configuration:
+ (++) Clock Timing
+ (++) Own Address 1
+ (++) Addressing mode (Master, Slave)
+ (++) Dual Addressing mode
+ (++) Own Address 2
+ (++) Own Address 2 Mask
+ (++) General call mode
+ (++) Nostretch mode
+
+ (+) Call the function HAL_I2C_DeInit() to restore the default configuration
+ of the selected I2Cx peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the I2C according to the specified parameters
+ * in the I2C_InitTypeDef and initialize the associated handle.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the I2C handle allocation */
+ if (hi2c == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1));
+ assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode));
+ assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode));
+ assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2));
+ assert_param(IS_I2C_OWN_ADDRESS2_MASK(hi2c->Init.OwnAddress2Masks));
+ assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode));
+ assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode));
+
+ if (hi2c->State == HAL_I2C_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hi2c->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ /* Init the I2C Callback settings */
+ hi2c->MasterTxCpltCallback = HAL_I2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
+ hi2c->MasterRxCpltCallback = HAL_I2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
+ hi2c->SlaveTxCpltCallback = HAL_I2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */
+ hi2c->SlaveRxCpltCallback = HAL_I2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */
+ hi2c->ListenCpltCallback = HAL_I2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */
+ hi2c->MemTxCpltCallback = HAL_I2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */
+ hi2c->MemRxCpltCallback = HAL_I2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */
+ hi2c->ErrorCallback = HAL_I2C_ErrorCallback; /* Legacy weak ErrorCallback */
+ hi2c->AbortCpltCallback = HAL_I2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ hi2c->AddrCallback = HAL_I2C_AddrCallback; /* Legacy weak AddrCallback */
+
+ if (hi2c->MspInitCallback == NULL)
+ {
+ hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */
+ }
+
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ hi2c->MspInitCallback(hi2c);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
+ HAL_I2C_MspInit(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /*---------------------------- I2Cx TIMINGR Configuration ------------------*/
+ /* Configure I2Cx: Frequency range */
+ hi2c->Instance->TIMINGR = hi2c->Init.Timing & TIMING_CLEAR_MASK;
+
+ /*---------------------------- I2Cx OAR1 Configuration ---------------------*/
+ /* Disable Own Address1 before set the Own Address1 configuration */
+ hi2c->Instance->OAR1 &= ~I2C_OAR1_OA1EN;
+
+ /* Configure I2Cx: Own Address1 and ack own address1 mode */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT)
+ {
+ hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | hi2c->Init.OwnAddress1);
+ }
+ else /* I2C_ADDRESSINGMODE_10BIT */
+ {
+ hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hi2c->Init.OwnAddress1);
+ }
+
+ /*---------------------------- I2Cx CR2 Configuration ----------------------*/
+ /* Configure I2Cx: Addressing Master mode */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ SET_BIT(hi2c->Instance->CR2, I2C_CR2_ADD10);
+ }
+ else
+ {
+ /* Clear the I2C ADD10 bit */
+ CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_ADD10);
+ }
+ /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */
+ hi2c->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK);
+
+ /*---------------------------- I2Cx OAR2 Configuration ---------------------*/
+ /* Disable Own Address2 before set the Own Address2 configuration */
+ hi2c->Instance->OAR2 &= ~I2C_DUALADDRESS_ENABLE;
+
+ /* Configure I2Cx: Dual mode and Own Address2 */
+ hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2 | \
+ (hi2c->Init.OwnAddress2Masks << 8));
+
+ /*---------------------------- I2Cx CR1 Configuration ----------------------*/
+ /* Configure I2Cx: Generalcall and NoStretch mode */
+ hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode);
+
+ /* Enable the selected I2C peripheral */
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the I2C peripheral.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the I2C handle allocation */
+ if (hi2c == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the I2C Peripheral Clock */
+ __HAL_I2C_DISABLE(hi2c);
+
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ if (hi2c->MspDeInitCallback == NULL)
+ {
+ hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ hi2c->MspDeInitCallback(hi2c);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_I2C_MspDeInit(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ hi2c->State = HAL_I2C_STATE_RESET;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the I2C MSP.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the I2C MSP.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User I2C Callback
+ * To be used instead of the weak predefined callback
+ * @note The HAL_I2C_RegisterCallback() may be called before HAL_I2C_Init() in HAL_I2C_STATE_RESET
+ * to register callbacks for HAL_I2C_MSPINIT_CB_ID and HAL_I2C_MSPDEINIT_CB_ID.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_I2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
+ * @arg @ref HAL_I2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID
+ * @arg @ref HAL_I2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_I2C_ABORT_CB_ID Abort callback ID
+ * @arg @ref HAL_I2C_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_I2C_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_RegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID,
+ pI2C_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MASTER_TX_COMPLETE_CB_ID :
+ hi2c->MasterTxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MASTER_RX_COMPLETE_CB_ID :
+ hi2c->MasterRxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_SLAVE_TX_COMPLETE_CB_ID :
+ hi2c->SlaveTxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_SLAVE_RX_COMPLETE_CB_ID :
+ hi2c->SlaveRxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_LISTEN_COMPLETE_CB_ID :
+ hi2c->ListenCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MEM_TX_COMPLETE_CB_ID :
+ hi2c->MemTxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MEM_RX_COMPLETE_CB_ID :
+ hi2c->MemRxCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_ERROR_CB_ID :
+ hi2c->ErrorCallback = pCallback;
+ break;
+
+ case HAL_I2C_ABORT_CB_ID :
+ hi2c->AbortCpltCallback = pCallback;
+ break;
+
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = pCallback;
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_I2C_STATE_RESET == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = pCallback;
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister an I2C Callback
+ * I2C callback is redirected to the weak predefined callback
+ * @note The HAL_I2C_UnRegisterCallback() may be called before HAL_I2C_Init() in HAL_I2C_STATE_RESET
+ * to un-register callbacks for HAL_I2C_MSPINIT_CB_ID and HAL_I2C_MSPDEINIT_CB_ID.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_I2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID
+ * @arg @ref HAL_I2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID
+ * @arg @ref HAL_I2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID
+ * @arg @ref HAL_I2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID
+ * @arg @ref HAL_I2C_ERROR_CB_ID Error callback ID
+ * @arg @ref HAL_I2C_ABORT_CB_ID Abort callback ID
+ * @arg @ref HAL_I2C_MSPINIT_CB_ID MspInit callback ID
+ * @arg @ref HAL_I2C_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_UnRegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MASTER_TX_COMPLETE_CB_ID :
+ hi2c->MasterTxCpltCallback = HAL_I2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */
+ break;
+
+ case HAL_I2C_MASTER_RX_COMPLETE_CB_ID :
+ hi2c->MasterRxCpltCallback = HAL_I2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */
+ break;
+
+ case HAL_I2C_SLAVE_TX_COMPLETE_CB_ID :
+ hi2c->SlaveTxCpltCallback = HAL_I2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */
+ break;
+
+ case HAL_I2C_SLAVE_RX_COMPLETE_CB_ID :
+ hi2c->SlaveRxCpltCallback = HAL_I2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */
+ break;
+
+ case HAL_I2C_LISTEN_COMPLETE_CB_ID :
+ hi2c->ListenCpltCallback = HAL_I2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */
+ break;
+
+ case HAL_I2C_MEM_TX_COMPLETE_CB_ID :
+ hi2c->MemTxCpltCallback = HAL_I2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */
+ break;
+
+ case HAL_I2C_MEM_RX_COMPLETE_CB_ID :
+ hi2c->MemRxCpltCallback = HAL_I2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */
+ break;
+
+ case HAL_I2C_ERROR_CB_ID :
+ hi2c->ErrorCallback = HAL_I2C_ErrorCallback; /* Legacy weak ErrorCallback */
+ break;
+
+ case HAL_I2C_ABORT_CB_ID :
+ hi2c->AbortCpltCallback = HAL_I2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
+ break;
+
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_I2C_STATE_RESET == hi2c->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_I2C_MSPINIT_CB_ID :
+ hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */
+ break;
+
+ case HAL_I2C_MSPDEINIT_CB_ID :
+ hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */
+ break;
+
+ default :
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register the Slave Address Match I2C Callback
+ * To be used instead of the weak HAL_I2C_AddrCallback() predefined callback
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pCallback pointer to the Address Match Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_RegisterAddrCallback(I2C_HandleTypeDef *hi2c, pI2C_AddrCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ hi2c->AddrCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief UnRegister the Slave Address Match I2C Callback
+ * Info Ready I2C Callback is redirected to the weak HAL_I2C_AddrCallback() predefined callback
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_UnRegisterAddrCallback(I2C_HandleTypeDef *hi2c)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_I2C_STATE_READY == hi2c->State)
+ {
+ hi2c->AddrCallback = HAL_I2C_AddrCallback; /* Legacy weak AddrCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Exported_Functions_Group2 Input and Output operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the I2C data
+ transfers.
+
+ (#) There are two modes of transfer:
+ (++) Blocking mode : The communication is performed in the polling mode.
+ The status of all data processing is returned by the same function
+ after finishing transfer.
+ (++) No-Blocking mode : The communication is performed using Interrupts
+ or DMA. These functions return the status of the transfer startup.
+ The end of the data processing will be indicated through the
+ dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (#) Blocking mode functions are :
+ (++) HAL_I2C_Master_Transmit()
+ (++) HAL_I2C_Master_Receive()
+ (++) HAL_I2C_Slave_Transmit()
+ (++) HAL_I2C_Slave_Receive()
+ (++) HAL_I2C_Mem_Write()
+ (++) HAL_I2C_Mem_Read()
+ (++) HAL_I2C_IsDeviceReady()
+
+ (#) No-Blocking mode functions with Interrupt are :
+ (++) HAL_I2C_Master_Transmit_IT()
+ (++) HAL_I2C_Master_Receive_IT()
+ (++) HAL_I2C_Slave_Transmit_IT()
+ (++) HAL_I2C_Slave_Receive_IT()
+ (++) HAL_I2C_Mem_Write_IT()
+ (++) HAL_I2C_Mem_Read_IT()
+ (++) HAL_I2C_Master_Seq_Transmit_IT()
+ (++) HAL_I2C_Master_Seq_Receive_IT()
+ (++) HAL_I2C_Slave_Seq_Transmit_IT()
+ (++) HAL_I2C_Slave_Seq_Receive_IT()
+ (++) HAL_I2C_EnableListen_IT()
+ (++) HAL_I2C_DisableListen_IT()
+ (++) HAL_I2C_Master_Abort_IT()
+
+ (#) No-Blocking mode functions with DMA are :
+ (++) HAL_I2C_Master_Transmit_DMA()
+ (++) HAL_I2C_Master_Receive_DMA()
+ (++) HAL_I2C_Slave_Transmit_DMA()
+ (++) HAL_I2C_Slave_Receive_DMA()
+ (++) HAL_I2C_Mem_Write_DMA()
+ (++) HAL_I2C_Mem_Read_DMA()
+ (++) HAL_I2C_Master_Seq_Transmit_DMA()
+ (++) HAL_I2C_Master_Seq_Receive_DMA()
+ (++) HAL_I2C_Slave_Seq_Transmit_DMA()
+ (++) HAL_I2C_Slave_Seq_Receive_DMA()
+
+ (#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_I2C_MasterTxCpltCallback()
+ (++) HAL_I2C_MasterRxCpltCallback()
+ (++) HAL_I2C_SlaveTxCpltCallback()
+ (++) HAL_I2C_SlaveRxCpltCallback()
+ (++) HAL_I2C_MemTxCpltCallback()
+ (++) HAL_I2C_MemRxCpltCallback()
+ (++) HAL_I2C_AddrCallback()
+ (++) HAL_I2C_ListenCpltCallback()
+ (++) HAL_I2C_ErrorCallback()
+ (++) HAL_I2C_AbortCpltCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmits in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint32_t xfermode;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)(hi2c->XferSize + 1U), xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ }
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receives in master mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ }
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmits in slave mode an amount of data in blocking mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+ uint16_t tmpXferCount;
+ HAL_StatusTypeDef error;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Preload TX data if no stretch enable */
+ if (hi2c->Init.NoStretchMode == I2C_NOSTRETCH_ENABLE)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ }
+
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* If 10bit addressing mode is selected */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Wait until DIR flag is set Transmitter mode */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ }
+
+ /* Wait until AF flag is set */
+ error = I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_AF, RESET, Timeout, tickstart);
+
+ if (error != HAL_OK)
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0 */
+
+ tmpXferCount = hi2c->XferCount;
+ if ((hi2c->ErrorCode == HAL_I2C_ERROR_AF) && (tmpXferCount == 0U))
+ {
+ /* Reset ErrorCode to NONE */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ else
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Clear AF flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Wait until STOP flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ /* Wait until BUSY flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in blocking mode
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferISR = NULL;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Wait until ADDR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Wait until DIR flag is reset Receiver mode */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ while (hi2c->XferCount > 0U)
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Store Last receive data if any */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET)
+ {
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* Wait until STOP flag is set */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Wait until BUSY flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK)
+ {
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+ return HAL_ERROR;
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
+ if (hi2c->XferSize > 0U)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)(hi2c->XferSize + 1U), xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode,
+ I2C_GENERATE_START_WRITE);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, I2C_GENERATE_START_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ /* Preload TX data if no stretch enable */
+ if (hi2c->Init.NoStretchMode == I2C_NOSTRETCH_ENABLE)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in master mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+ HAL_StatusTypeDef dmaxferstatus;
+ uint32_t sizetoxfer = 0U;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ sizetoxfer = hi2c->XferSize;
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr,
+ (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)(hi2c->XferSize + 1U),
+ xfermode, I2C_GENERATE_START_WRITE);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and generate START condition */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in master mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size)
+{
+ uint32_t xfermode;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = I2C_AUTOEND_MODE;
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address */
+ /* Set NBYTES to read and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, I2C_GENERATE_START_READ);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to read and generate START condition */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ /* Preload TX data if no stretch enable */
+ if (hi2c->Init.NoStretchMode == I2C_NOSTRETCH_ENABLE)
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ if (hi2c->XferCount != 0U)
+ {
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx,
+ (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive in slave mode an amount of data in non-blocking mode with DMA
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Write an amount of data in blocking mode to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address and Memory Address */
+ if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ do
+ {
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+
+ } while (hi2c->XferCount > 0U);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in blocking mode from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Init tickstart for timeout management*/
+ tickstart = HAL_GetTick();
+
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferISR = NULL;
+
+ /* Send Slave Address and Memory Address */
+ if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_GENERATE_START_READ);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+ }
+
+ do
+ {
+ /* Wait until RXNE flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t) hi2c->XferSize, I2C_RELOAD_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_NO_STARTSTOP);
+ }
+ }
+ } while (hi2c->XferCount > 0U);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->XferSize = 0U;
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_IT;
+ hi2c->Devaddress = DevAddress;
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_IT;
+ hi2c->Devaddress = DevAddress;
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_DMA;
+ hi2c->Devaddress = DevAddress;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
+ uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MEM;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferISR = I2C_Mem_ISR_DMA;
+ hi2c->Devaddress = DevAddress;
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Prefetch Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Prepare Memaddress buffer for LSB part */
+ hi2c->Memaddress = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and Memory Address */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Checks if target device is ready for communication.
+ * @note This function is used with Memory devices
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param Trials Number of trials
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ __IO uint32_t I2C_Trials = 0UL;
+
+ FlagStatus tmp1;
+ FlagStatus tmp2;
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET)
+ {
+ return HAL_BUSY;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ do
+ {
+ /* Generate Start */
+ hi2c->Instance->CR2 = I2C_GENERATE_START(hi2c->Init.AddressingMode, DevAddress);
+
+ /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */
+ /* Wait until STOPF flag is set or a NACK flag is set*/
+ tickstart = HAL_GetTick();
+
+ tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
+ tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
+
+ while ((tmp1 == RESET) && (tmp2 == RESET))
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+
+ tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF);
+ tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF);
+ }
+
+ /* Check if the NACKF flag has not been set */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET)
+ {
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK)
+ {
+ /* A non acknowledge appear during STOP Flag waiting process, a new trial must be performed */
+ if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Reset the error code for next trial */
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ }
+ else
+ {
+ /* A acknowledge appear during STOP Flag waiting process, this mean that device respond to its address */
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Device is ready */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ }
+ else
+ {
+ /* A non acknowledge is detected, this mean that device not respond to its address,
+ a new trial must be performed */
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Wait until STOPF flag is reset */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) == HAL_OK)
+ {
+ /* Clear STOP Flag, auto generated with autoend*/
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+ }
+
+ /* Increment Trials */
+ I2C_Trials++;
+ } while (I2C_Trials < Trials);
+
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with Interrupt.
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_WRITE;
+ uint32_t sizetoxfer = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ if ((hi2c->XferSize > 0U) && ((XferOptions == I2C_FIRST_FRAME) || \
+ (XferOptions == I2C_FIRST_AND_LAST_FRAME)))
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ sizetoxfer = hi2c->XferSize;
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ /* Send Slave Address and set NBYTES to write */
+ if ((XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_FIRST_AND_LAST_FRAME))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with DMA.
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_WRITE;
+ HAL_StatusTypeDef dmaxferstatus;
+ uint32_t sizetoxfer = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ if ((hi2c->XferSize > 0U) && ((XferOptions == I2C_FIRST_FRAME) || \
+ (XferOptions == I2C_FIRST_AND_LAST_FRAME)))
+ {
+ /* Preload TX register */
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ sizetoxfer = hi2c->XferSize;
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr,
+ (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and set NBYTES to write */
+ if ((XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_FIRST_AND_LAST_FRAME))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+ }
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to write and generate START condition */
+ if ((XferOptions == I2C_FIRST_FRAME) || (XferOptions == I2C_FIRST_AND_LAST_FRAME))
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, TXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_READ;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ /* Send Slave Address and set NBYTES to read */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with DMA
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
+ uint16_t Size, uint32_t XferOptions)
+{
+ uint32_t xfermode;
+ uint32_t xferrequest = I2C_GENERATE_START_READ;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX;
+ hi2c->Mode = HAL_I2C_MODE_MASTER;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Master_ISR_DMA;
+
+ /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ xfermode = hi2c->XferOptions;
+ }
+
+ /* If transfer direction not change and there is no request to start another frame,
+ do not generate Restart Condition */
+ /* Mean Previous state is same as current state */
+ if ((hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) && \
+ (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0))
+ {
+ xferrequest = I2C_NO_STARTSTOP;
+ }
+ else
+ {
+ /* Convert OTHER_xxx XferOptions if any */
+ I2C_ConvertOtherXferOptions(hi2c);
+
+ /* Update xfermode accordingly if no reload is necessary */
+ if (hi2c->XferCount <= MAX_NBYTE_SIZE)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ }
+
+ if (hi2c->XferSize > 0U)
+ {
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Send Slave Address and set NBYTES to read */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, xfermode, xferrequest);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR and NACK interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Update Transfer ISR function pointer */
+ hi2c->XferISR = I2C_Master_ISR_IT;
+
+ /* Send Slave Address */
+ /* Set NBYTES to read and generate START condition */
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)hi2c->XferSize, I2C_AUTOEND_MODE,
+ I2C_GENERATE_START_READ);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, TC, STOP, NACK, RXI interrupt */
+ /* possible to enable all of these */
+ /* I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI |
+ I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+ }
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave RX state to TX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Abort DMA Xfer if any */
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ }
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with DMA
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave RX state to TX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmarx != NULL)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ }
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmatx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmatx->XferHalfCpltCallback = NULL;
+ hi2c->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Reset XferSize */
+ hi2c->XferSize = 0;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* Enable ERR, STOP, NACK, ADDR interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with Interrupt
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave TX state to RX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmatx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ }
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with DMA
+ * @note This interface allow to manage repeated start condition when a direction change during transfer
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size,
+ uint32_t XferOptions)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ FlagStatus tmp;
+ HAL_StatusTypeDef dmaxferstatus;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions));
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_INVALID_PARAM;
+ return HAL_ERROR;
+ }
+
+ /* Disable Interrupts, to prevent preemption during treatment in case of multicall */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */
+ /* and then toggle the HAL slave TX state to RX state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ /* Disable associated Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmatx != NULL)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ }
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Abort DMA Xfer if any */
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_SLAVE;
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+
+ /* Enable Address Acknowledge */
+ hi2c->Instance->CR2 &= ~I2C_CR2_NACK;
+
+ /* Prepare transfer parameters */
+ hi2c->pBuffPtr = pData;
+ hi2c->XferCount = Size;
+ hi2c->XferSize = hi2c->XferCount;
+ hi2c->XferOptions = XferOptions;
+ hi2c->XferISR = I2C_Slave_ISR_DMA;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ /* Set the I2C DMA transfer complete callback */
+ hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt;
+
+ /* Set the DMA error callback */
+ hi2c->hdmarx->XferErrorCallback = I2C_DMAError;
+
+ /* Set the unused DMA callbacks to NULL */
+ hi2c->hdmarx->XferHalfCpltCallback = NULL;
+ hi2c->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the DMA stream or channel depends on Instance */
+ dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR,
+ (uint32_t)pData, hi2c->XferSize);
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ if (dmaxferstatus == HAL_OK)
+ {
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Reset XferSize */
+ hi2c->XferSize = 0;
+ }
+ else
+ {
+ /* Update I2C state */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Update I2C error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_DMA;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+
+ tmp = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR);
+ if ((I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT) && (tmp != RESET))
+ {
+ /* Clear ADDR flag after prepare the transfer parameters */
+ /* This action will generate an acknowledge to the Master */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Enable DMA Request */
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ /* REnable ADDR interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Enable the Address listen mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c)
+{
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+
+ /* Enable the Address Match interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disable the Address listen mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c)
+{
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ uint32_t tmp;
+
+ /* Disable Address listen mode only if a transfer is not ongoing */
+ if (hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK;
+ hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode);
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferISR = NULL;
+
+ /* Disable the Address Match interrupt */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Abort a master or memory I2C IT or DMA process communication with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress)
+{
+ HAL_I2C_ModeTypeDef tmp_mode = hi2c->Mode;
+
+ if ((tmp_mode == HAL_I2C_MODE_MASTER) || (tmp_mode == HAL_I2C_MODE_MEM))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ /* Disable Interrupts and Store Previous state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Set State at HAL_I2C_STATE_ABORT */
+ hi2c->State = HAL_I2C_STATE_ABORT;
+
+ /* Set NBYTES to 1 to generate a dummy read on I2C peripheral */
+ /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */
+ I2C_TransferConfig(hi2c, DevAddress, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Note : The I2C interrupts must be enabled after unlocking current process
+ to avoid the risk of I2C interrupt handle execution before current
+ process unlock */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+
+ return HAL_OK;
+ }
+ else
+ {
+ /* Wrong usage of abort function */
+ /* This function should be used only in case of abort monitored by master device */
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks
+ * @{
+ */
+
+/**
+ * @brief This function handles I2C event interrupt request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) /* Derogation MISRAC2012-Rule-8.13 */
+{
+ /* Get current IT Flags and IT sources value */
+ uint32_t itflags = READ_REG(hi2c->Instance->ISR);
+ uint32_t itsources = READ_REG(hi2c->Instance->CR1);
+
+ /* I2C events treatment -------------------------------------*/
+ if (hi2c->XferISR != NULL)
+ {
+ hi2c->XferISR(hi2c, itflags, itsources);
+ }
+}
+
+/**
+ * @brief This function handles I2C error interrupt request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c)
+{
+ uint32_t itflags = READ_REG(hi2c->Instance->ISR);
+ uint32_t itsources = READ_REG(hi2c->Instance->CR1);
+ uint32_t tmperror;
+
+ /* I2C Bus error interrupt occurred ------------------------------------*/
+ if ((I2C_CHECK_FLAG(itflags, I2C_FLAG_BERR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERRI) != RESET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_BERR;
+
+ /* Clear BERR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
+ }
+
+ /* I2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/
+ if ((I2C_CHECK_FLAG(itflags, I2C_FLAG_OVR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERRI) != RESET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_OVR;
+
+ /* Clear OVR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
+ }
+
+ /* I2C Arbitration Loss error interrupt occurred -------------------------------------*/
+ if ((I2C_CHECK_FLAG(itflags, I2C_FLAG_ARLO) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERRI) != RESET))
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO;
+
+ /* Clear ARLO flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
+ }
+
+ /* Store current volatile hi2c->ErrorCode, misra rule */
+ tmperror = hi2c->ErrorCode;
+
+ /* Call the Error Callback in case of Error detected */
+ if ((tmperror & (HAL_I2C_ERROR_BERR | HAL_I2C_ERROR_OVR | HAL_I2C_ERROR_ARLO)) != HAL_I2C_ERROR_NONE)
+ {
+ I2C_ITError(hi2c, tmperror);
+ }
+}
+
+/**
+ * @brief Master Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MasterTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Master Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MasterRxCpltCallback could be implemented in the user file
+ */
+}
+
+/** @brief Slave Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Slave Address Match callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XFERDIRECTION
+ * @param AddrMatchCode Address Match Code
+ * @retval None
+ */
+__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+ UNUSED(TransferDirection);
+ UNUSED(AddrMatchCode);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_AddrCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Listen Complete callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_ListenCpltCallback() could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Tx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MemTxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Memory Rx Transfer completed callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_MemRxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C error callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief I2C abort callback.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval None
+ */
+__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hi2c);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_I2C_AbortCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions
+ * @brief Peripheral State, Mode and Error functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State, Mode and Error functions #####
+ ===============================================================================
+ [..]
+ This subsection permit to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the I2C handle state.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval HAL state
+ */
+HAL_I2C_StateTypeDef HAL_I2C_GetState(const I2C_HandleTypeDef *hi2c)
+{
+ /* Return I2C handle state */
+ return hi2c->State;
+}
+
+/**
+ * @brief Returns the I2C Master, Slave, Memory or no mode.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for I2C module
+ * @retval HAL mode
+ */
+HAL_I2C_ModeTypeDef HAL_I2C_GetMode(const I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->Mode;
+}
+
+/**
+ * @brief Return the I2C error code.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @retval I2C Error Code
+ */
+uint32_t HAL_I2C_GetError(const I2C_HandleTypeDef *hi2c)
+{
+ return hi2c->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup I2C_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint16_t devaddress;
+ uint32_t tmpITFlags = ITFlags;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ /* No need to generate STOP, it is automatically done */
+ /* Error callback will be send during stop flag treatment */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_RXI) != RESET))
+ {
+ /* Remove RXNE flag on temporary variable as read done */
+ tmpITFlags &= ~I2C_FLAG_RXNE;
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TC) == RESET) && \
+ ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET)))
+ {
+ /* Write data to TXDR */
+ if (hi2c->XferCount != 0U)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ devaddress = (uint16_t)(hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ if (hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize,
+ hi2c->XferOptions, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ }
+ else
+ {
+ /* Call TxCpltCallback() if no stop mode is set */
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if (hi2c->XferCount == 0U)
+ {
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Generate a stop condition in case of no transfer option */
+ if (hi2c->XferOptions == I2C_NO_OPTION_FRAME)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ else
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TC flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, tmpITFlags);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Mem_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t direction = I2C_GENERATE_START_WRITE;
+ uint32_t tmpITFlags = ITFlags;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ /* No need to generate STOP, it is automatically done */
+ /* Error callback will be send during stop flag treatment */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_RXI) != RESET))
+ {
+ /* Remove RXNE flag on temporary variable as read done */
+ tmpITFlags &= ~I2C_FLAG_RXNE;
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ if (hi2c->Memaddress == 0xFFFFFFFFU)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ else
+ {
+ /* Write LSB part of Memory Address */
+ hi2c->Instance->TXDR = hi2c->Memaddress;
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if ((hi2c->XferCount != 0U) && (hi2c->XferSize == 0U))
+ {
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable Interrupt related to address step */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Enable ERR, TC, STOP, NACK and RXI interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ direction = I2C_GENERATE_START_READ;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, direction);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+
+ /* Set NBYTES to write and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, direction);
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, tmpITFlags);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t tmpoptions = hi2c->XferOptions;
+ uint32_t tmpITFlags = ITFlags;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ /* Check if STOPF is set */
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Slave complete process */
+ I2C_ITSlaveCplt(hi2c, tmpITFlags);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if (hi2c->XferCount == 0U)
+ {
+ if ((hi2c->State == HAL_I2C_STATE_LISTEN) && (tmpoptions == I2C_FIRST_AND_LAST_FRAME))
+ /* Same action must be done for (tmpoptions == I2C_LAST_FRAME) which removed for
+ Warning[Pa134]: left and right operands are identical */
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, tmpITFlags);
+ }
+ else if ((hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ if ((tmpoptions == I2C_FIRST_FRAME) || (tmpoptions == I2C_NEXT_FRAME))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_RXI) != RESET))
+ {
+ if (hi2c->XferCount > 0U)
+ {
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+
+ if ((hi2c->XferCount == 0U) && \
+ (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_ADDR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_ADDRI) != RESET))
+ {
+ I2C_ITAddrCplt(hi2c, tmpITFlags);
+ }
+ else if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ /* Write data to TXDR only if XferCount not reach "0" */
+ /* A TXIS flag can be set, during STOP treatment */
+ /* Check if all Data have already been sent */
+ /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */
+ if (hi2c->XferCount > 0U)
+ {
+ /* Write data to TXDR */
+ hi2c->Instance->TXDR = *hi2c->pBuffPtr;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ hi2c->XferCount--;
+ hi2c->XferSize--;
+ }
+ else
+ {
+ if ((tmpoptions == I2C_NEXT_FRAME) || (tmpoptions == I2C_FIRST_FRAME))
+ {
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with DMA.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint16_t devaddress;
+ uint32_t xfermode;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* No need to generate STOP, it is automatically done */
+ /* But enable STOP interrupt, to treat it */
+ /* Error callback will be send during stop flag treatment */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable TC interrupt */
+ __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_TCI);
+
+ if (hi2c->XferCount != 0U)
+ {
+ /* Recover Slave address */
+ devaddress = (uint16_t)(hi2c->Instance->CR2 & I2C_CR2_SADD);
+
+ /* Prepare the new XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ xfermode = I2C_RELOAD_MODE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ if (hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ xfermode = hi2c->XferOptions;
+ }
+ else
+ {
+ xfermode = I2C_AUTOEND_MODE;
+ }
+ }
+
+ /* Set the new XferSize in Nbytes register */
+ I2C_TransferConfig(hi2c, devaddress, (uint8_t)hi2c->XferSize, xfermode, I2C_NO_STARTSTOP);
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Enable DMA Request */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ else
+ {
+ /* Call TxCpltCallback() if no stop mode is set */
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ if (hi2c->XferCount == 0U)
+ {
+ if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE)
+ {
+ /* Generate a stop condition in case of no transfer option */
+ if (hi2c->XferOptions == I2C_NO_OPTION_FRAME)
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+ }
+ else
+ {
+ /* Call I2C Master Sequential complete process */
+ I2C_ITMasterSeqCplt(hi2c);
+ }
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TC flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, ITFlags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with DMA.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Mem_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t direction = I2C_GENERATE_START_WRITE;
+
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set corresponding Error Code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* No need to generate STOP, it is automatically done */
+ /* But enable STOP interrupt, to treat it */
+ /* Error callback will be send during stop flag treatment */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TXIS) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TXI) != RESET))
+ {
+ /* Write LSB part of Memory Address */
+ hi2c->Instance->TXDR = hi2c->Memaddress;
+
+ /* Reset Memaddress content */
+ hi2c->Memaddress = 0xFFFFFFFFU;
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TCR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable Interrupt related to address step */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Enable only Error interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ if (hi2c->XferCount != 0U)
+ {
+ /* Prepare the new XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, I2C_NO_STARTSTOP);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, I2C_NO_STARTSTOP);
+ }
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Enable DMA Request */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ else
+ {
+ /* Wrong size Status regarding TCR flag event */
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_TC) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_TCI) != RESET))
+ {
+ /* Disable Interrupt related to address step */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Enable only Error and NACK interrupt for data transfer */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT);
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ direction = I2C_GENERATE_START_READ;
+ }
+
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+
+ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_RELOAD_MODE, direction);
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+
+ /* Set NBYTES to write and generate RESTART */
+ I2C_TransferConfig(hi2c, (uint16_t)hi2c->Devaddress, (uint8_t)hi2c->XferSize,
+ I2C_AUTOEND_MODE, direction);
+ }
+
+ /* Update XferCount value */
+ hi2c->XferCount -= hi2c->XferSize;
+
+ /* Enable DMA Request */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN;
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Master complete process */
+ I2C_ITMasterCplt(hi2c, ITFlags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param ITFlags Interrupt flags to handle.
+ * @param ITSources Interrupt sources enabled.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags,
+ uint32_t ITSources)
+{
+ uint32_t tmpoptions = hi2c->XferOptions;
+ uint32_t treatdmanack = 0U;
+ HAL_I2C_StateTypeDef tmpstate;
+
+ /* Process locked */
+ __HAL_LOCK(hi2c);
+
+ /* Check if STOPF is set */
+ if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_STOPF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_STOPI) != RESET))
+ {
+ /* Call I2C Slave complete process */
+ I2C_ITSlaveCplt(hi2c, ITFlags);
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_NACKI) != RESET))
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0 */
+ /* So clear Flag NACKF only */
+ if ((I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_TXDMAEN) != RESET) ||
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_RXDMAEN) != RESET))
+ {
+ /* Split check of hdmarx, for MISRA compliance */
+ if (hi2c->hdmarx != NULL)
+ {
+ if (I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_RXDMAEN) != RESET)
+ {
+ if (I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx) == 0U)
+ {
+ treatdmanack = 1U;
+ }
+ }
+ }
+
+ /* Split check of hdmatx, for MISRA compliance */
+ if (hi2c->hdmatx != NULL)
+ {
+ if (I2C_CHECK_IT_SOURCE(ITSources, I2C_CR1_TXDMAEN) != RESET)
+ {
+ if (I2C_GET_DMA_REMAIN_DATA(hi2c->hdmatx) == 0U)
+ {
+ treatdmanack = 1U;
+ }
+ }
+ }
+
+ if (treatdmanack == 1U)
+ {
+ if ((hi2c->State == HAL_I2C_STATE_LISTEN) && (tmpoptions == I2C_FIRST_AND_LAST_FRAME))
+ /* Same action must be done for (tmpoptions == I2C_LAST_FRAME) which removed for
+ Warning[Pa134]: left and right operands are identical */
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, ITFlags);
+ }
+ else if ((hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ /* Store current hi2c->State, solve MISRA2012-Rule-13.5 */
+ tmpstate = hi2c->State;
+
+ if ((tmpoptions == I2C_FIRST_FRAME) || (tmpoptions == I2C_NEXT_FRAME))
+ {
+ if ((tmpstate == HAL_I2C_STATE_BUSY_TX) || (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN))
+ {
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+ }
+ else if ((tmpstate == HAL_I2C_STATE_BUSY_RX) || (tmpstate == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ }
+ }
+ else
+ {
+ /* Only Clear NACK Flag, no DMA treatment is pending */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else if ((I2C_CHECK_FLAG(ITFlags, I2C_FLAG_ADDR) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(ITSources, I2C_IT_ADDRI) != RESET))
+ {
+ I2C_ITAddrCplt(hi2c, ITFlags);
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Master sends target device address followed by internal memory address for write request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Send Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Send MSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Send LSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ /* Wait until TCR flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Master sends target device address followed by internal memory address for read request.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param DevAddress Target device address: The device 7 bits address value
+ * in datasheet must be shifted to the left before calling the interface
+ * @param MemAddress Internal memory address
+ * @param MemAddSize Size of internal memory address
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
+ uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ I2C_TransferConfig(hi2c, DevAddress, (uint8_t)MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* If Memory address size is 8Bit */
+ if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
+ {
+ /* Send Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+ /* If Memory address size is 16Bit */
+ else
+ {
+ /* Send MSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress);
+
+ /* Wait until TXIS flag is set */
+ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Send LSB of Memory Address */
+ hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress);
+ }
+
+ /* Wait until TC flag is set */
+ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief I2C Address complete process callback.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ uint8_t transferdirection;
+ uint16_t slaveaddrcode;
+ uint16_t ownadd1code;
+ uint16_t ownadd2code;
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(ITFlags);
+
+ /* In case of Listen state, need to inform upper layer of address match code event */
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ transferdirection = I2C_GET_DIR(hi2c);
+ slaveaddrcode = I2C_GET_ADDR_MATCH(hi2c);
+ ownadd1code = I2C_GET_OWN_ADDRESS1(hi2c);
+ ownadd2code = I2C_GET_OWN_ADDRESS2(hi2c);
+
+ /* If 10bits addressing mode is selected */
+ if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)
+ {
+ if ((slaveaddrcode & SLAVE_ADDR_MSK) == ((ownadd1code >> SLAVE_ADDR_SHIFT) & SLAVE_ADDR_MSK))
+ {
+ slaveaddrcode = ownadd1code;
+ hi2c->AddrEventCount++;
+ if (hi2c->AddrEventCount == 2U)
+ {
+ /* Reset Address Event counter */
+ hi2c->AddrEventCount = 0U;
+
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#else
+ HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ slaveaddrcode = ownadd2code;
+
+ /* Disable ADDR Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#else
+ HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ /* else 7 bits addressing mode is selected */
+ else
+ {
+ /* Disable ADDR Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call Slave Addr callback */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#else
+ HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ /* Else clear address flag only */
+ else
+ {
+ /* Clear ADDR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+}
+
+/**
+ * @brief I2C Master sequential complete process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_ITMasterSeqCplt(I2C_HandleTypeDef *hi2c)
+{
+ /* Reset I2C handle mode */
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* No Generate Stop, to permit restart mode */
+ /* The stop will be done at the end of transfer, when I2C_AUTOEND_MODE enable */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ hi2c->XferISR = NULL;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterTxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_RX */
+ else
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ hi2c->XferISR = NULL;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterRxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief I2C Slave sequential complete process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_ITSlaveSeqCplt(I2C_HandleTypeDef *hi2c)
+{
+ uint32_t tmpcr1value = READ_REG(hi2c->Instance->CR1);
+
+ /* Reset I2C handle mode */
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* If a DMA is ongoing, Update handle size context */
+ if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_TXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+ }
+ else if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_RXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)
+ {
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_TX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveTxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)
+ {
+ /* Remove HAL_I2C_STATE_SLAVE_BUSY_RX, keep only HAL_I2C_STATE_LISTEN */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+
+ /* Disable Interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveRxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief I2C Master complete process.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ uint32_t tmperror;
+ uint32_t tmpITFlags = ITFlags;
+ __IO uint32_t tmpreg;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Disable Interrupts and Store Previous state */
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX;
+ }
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Reset handle parameters */
+ hi2c->XferISR = NULL;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+
+ if (I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET)
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set acknowledge error code */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ /* Fetch Last receive data if any */
+ if ((hi2c->State == HAL_I2C_STATE_ABORT) && (I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET))
+ {
+ /* Read data from RXDR */
+ tmpreg = (uint8_t)hi2c->Instance->RXDR;
+ UNUSED(tmpreg);
+ }
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Store current volatile hi2c->ErrorCode, misra rule */
+ tmperror = hi2c->ErrorCode;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ if ((hi2c->State == HAL_I2C_STATE_ABORT) || (tmperror != HAL_I2C_ERROR_NONE))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_TX */
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_TX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ if (hi2c->Mode == HAL_I2C_MODE_MEM)
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MemTxCpltCallback(hi2c);
+#else
+ HAL_I2C_MemTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterTxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ /* hi2c->State == HAL_I2C_STATE_BUSY_RX */
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ if (hi2c->Mode == HAL_I2C_MODE_MEM)
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MemRxCpltCallback(hi2c);
+#else
+ HAL_I2C_MemRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->MasterRxCpltCallback(hi2c);
+#else
+ HAL_I2C_MasterRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief I2C Slave complete process.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ uint32_t tmpcr1value = READ_REG(hi2c->Instance->CR1);
+ uint32_t tmpITFlags = ITFlags;
+ uint32_t tmpoptions = hi2c->XferOptions;
+ HAL_I2C_StateTypeDef tmpstate = hi2c->State;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Disable Interrupts and Store Previous state */
+ if ((tmpstate == HAL_I2C_STATE_BUSY_TX) || (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN))
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT);
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX;
+ }
+ else if ((tmpstate == HAL_I2C_STATE_BUSY_RX) || (tmpstate == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX;
+ }
+ else if (tmpstate == HAL_I2C_STATE_LISTEN)
+ {
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT | I2C_XFER_RX_IT);
+ hi2c->PreviousState = I2C_STATE_NONE;
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Disable Address Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* If a DMA is ongoing, Update handle size context */
+ if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_TXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ if (hi2c->hdmatx != NULL)
+ {
+ hi2c->XferCount = (uint16_t)I2C_GET_DMA_REMAIN_DATA(hi2c->hdmatx);
+ }
+ }
+ else if (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_CR1_RXDMAEN) != RESET)
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ if (hi2c->hdmarx != NULL)
+ {
+ hi2c->XferCount = (uint16_t)I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx);
+ }
+ }
+ else
+ {
+ /* Do nothing */
+ }
+
+ /* Store Last receive data if any */
+ if (I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_RXNE) != RESET)
+ {
+ /* Remove RXNE flag on temporary variable as read done */
+ tmpITFlags &= ~I2C_FLAG_RXNE;
+
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ if (hi2c->XferSize > 0U)
+ {
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+ }
+ }
+
+ /* All data are not transferred, so set error code accordingly */
+ if (hi2c->XferCount != 0U)
+ {
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ if ((I2C_CHECK_FLAG(tmpITFlags, I2C_FLAG_AF) != RESET) && \
+ (I2C_CHECK_IT_SOURCE(tmpcr1value, I2C_IT_NACKI) != RESET))
+ {
+ /* Check that I2C transfer finished */
+ /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */
+ /* Mean XferCount == 0*/
+ /* So clear Flag NACKF only */
+ if (hi2c->XferCount == 0U)
+ {
+ if ((hi2c->State == HAL_I2C_STATE_LISTEN) && (tmpoptions == I2C_FIRST_AND_LAST_FRAME))
+ /* Same action must be done for (tmpoptions == I2C_LAST_FRAME) which removed for
+ Warning[Pa134]: left and right operands are identical */
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, tmpITFlags);
+ }
+ else if ((hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ }
+ }
+ else
+ {
+ /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+
+ if ((tmpoptions == I2C_FIRST_FRAME) || (tmpoptions == I2C_NEXT_FRAME))
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+ }
+ }
+ }
+
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferISR = NULL;
+
+ if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, hi2c->ErrorCode);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+ if (hi2c->State == HAL_I2C_STATE_LISTEN)
+ {
+ /* Call I2C Listen complete process */
+ I2C_ITListenCplt(hi2c, tmpITFlags);
+ }
+ }
+ else if (hi2c->XferOptions != I2C_NO_OPTION_FRAME)
+ {
+ /* Call the Sequential Complete callback, to inform upper layer of the end of Transfer */
+ I2C_ITSlaveSeqCplt(hi2c);
+
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->ListenCpltCallback(hi2c);
+#else
+ HAL_I2C_ListenCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ else if (hi2c->State == HAL_I2C_STATE_BUSY_RX)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveRxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveRxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->SlaveTxCpltCallback(hi2c);
+#else
+ HAL_I2C_SlaveTxCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief I2C Listen complete process.
+ * @param hi2c I2C handle.
+ * @param ITFlags Interrupt flags to handle.
+ * @retval None
+ */
+static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags)
+{
+ /* Reset handle parameters */
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->PreviousState = I2C_STATE_NONE;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferISR = NULL;
+
+ /* Store Last receive data if any */
+ if (I2C_CHECK_FLAG(ITFlags, I2C_FLAG_RXNE) != RESET)
+ {
+ /* Read data from RXDR */
+ *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->RXDR;
+
+ /* Increment Buffer pointer */
+ hi2c->pBuffPtr++;
+
+ if (hi2c->XferSize > 0U)
+ {
+ hi2c->XferSize--;
+ hi2c->XferCount--;
+
+ /* Set ErrorCode corresponding to a Non-Acknowledge */
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+ }
+
+ /* Disable all Interrupts*/
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* Clear NACK Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->ListenCpltCallback(hi2c);
+#else
+ HAL_I2C_ListenCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief I2C interrupts error process.
+ * @param hi2c I2C handle.
+ * @param ErrorCode Error code to handle.
+ * @retval None
+ */
+static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode)
+{
+ HAL_I2C_StateTypeDef tmpstate = hi2c->State;
+
+ uint32_t tmppreviousstate;
+
+ /* Reset handle parameters */
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+ hi2c->XferOptions = I2C_NO_OPTION_FRAME;
+ hi2c->XferCount = 0U;
+
+ /* Set new error code */
+ hi2c->ErrorCode |= ErrorCode;
+
+ /* Disable Interrupts */
+ if ((tmpstate == HAL_I2C_STATE_LISTEN) ||
+ (tmpstate == HAL_I2C_STATE_BUSY_TX_LISTEN) ||
+ (tmpstate == HAL_I2C_STATE_BUSY_RX_LISTEN))
+ {
+ /* Disable all interrupts, except interrupts related to LISTEN state */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* keep HAL_I2C_STATE_LISTEN if set */
+ hi2c->State = HAL_I2C_STATE_LISTEN;
+ hi2c->XferISR = I2C_Slave_ISR_IT;
+ }
+ else
+ {
+ /* Disable all interrupts */
+ I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT);
+
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* If state is an abort treatment on going, don't change state */
+ /* This change will be do later */
+ if (hi2c->State != HAL_I2C_STATE_ABORT)
+ {
+ /* Set HAL_I2C_STATE_READY */
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Check if a STOPF is detected */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET)
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ hi2c->ErrorCode |= HAL_I2C_ERROR_AF;
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ }
+ hi2c->XferISR = NULL;
+ }
+
+ /* Abort DMA TX transfer if any */
+ tmppreviousstate = hi2c->PreviousState;
+
+ if ((hi2c->hdmatx != NULL) && ((tmppreviousstate == I2C_STATE_MASTER_BUSY_TX) || \
+ (tmppreviousstate == I2C_STATE_SLAVE_BUSY_TX)))
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+ }
+
+ if (HAL_DMA_GetState(hi2c->hdmatx) != HAL_DMA_STATE_READY)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Abort DMA TX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK)
+ {
+ /* Call Directly XferAbortCallback function in case of error */
+ hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx);
+ }
+ }
+ else
+ {
+ I2C_TreatErrorCallback(hi2c);
+ }
+ }
+ /* Abort DMA RX transfer if any */
+ else if ((hi2c->hdmarx != NULL) && ((tmppreviousstate == I2C_STATE_MASTER_BUSY_RX) || \
+ (tmppreviousstate == I2C_STATE_SLAVE_BUSY_RX)))
+ {
+ if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)
+ {
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+ }
+
+ if (HAL_DMA_GetState(hi2c->hdmarx) != HAL_DMA_STATE_READY)
+ {
+ /* Set the I2C DMA Abort callback :
+ will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */
+ hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Abort DMA RX */
+ if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK)
+ {
+ /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */
+ hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx);
+ }
+ }
+ else
+ {
+ I2C_TreatErrorCallback(hi2c);
+ }
+ }
+ else
+ {
+ I2C_TreatErrorCallback(hi2c);
+ }
+}
+
+/**
+ * @brief I2C Error callback treatment.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_TreatErrorCallback(I2C_HandleTypeDef *hi2c)
+{
+ if (hi2c->State == HAL_I2C_STATE_ABORT)
+ {
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->AbortCpltCallback(hi2c);
+#else
+ HAL_I2C_AbortCpltCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ hi2c->PreviousState = I2C_STATE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
+ hi2c->ErrorCallback(hi2c);
+#else
+ HAL_I2C_ErrorCallback(hi2c);
+#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief I2C Tx data register flush process.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c)
+{
+ /* If a pending TXIS flag is set */
+ /* Write a dummy data in TXDR to clear it */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET)
+ {
+ hi2c->Instance->TXDR = 0x00U;
+ }
+
+ /* Flush TX register if not empty */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE);
+ }
+}
+
+/**
+ * @brief DMA I2C master transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* If last transfer, enable STOP interrupt */
+ if (hi2c->XferCount == 0U)
+ {
+ /* Enable STOP interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+ }
+ /* else prepare a new DMA transfer and enable TCReload interrupt */
+ else
+ {
+ /* Update Buffer pointer */
+ hi2c->pBuffPtr += hi2c->XferSize;
+
+ /* Set the XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* Enable the DMA stream or channel depends on Instance */
+ if (HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR,
+ hi2c->XferSize) != HAL_OK)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
+ }
+ else
+ {
+ /* Enable TC interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT);
+ }
+ }
+}
+
+
+/**
+ * @brief DMA I2C slave transmit process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tmpoptions = hi2c->XferOptions;
+
+ if ((tmpoptions == I2C_NEXT_FRAME) || (tmpoptions == I2C_FIRST_FRAME))
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN;
+
+ /* Last Byte is Transmitted */
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* No specific action, Master fully manage the generation of STOP condition */
+ /* Mean that this generation can arrive at any time, at the end or during DMA process */
+ /* So STOP condition should be manage through Interrupt treatment */
+ }
+}
+
+
+/**
+ * @brief DMA I2C master receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* If last transfer, enable STOP interrupt */
+ if (hi2c->XferCount == 0U)
+ {
+ /* Enable STOP interrupt */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT);
+ }
+ /* else prepare a new DMA transfer and enable TCReload interrupt */
+ else
+ {
+ /* Update Buffer pointer */
+ hi2c->pBuffPtr += hi2c->XferSize;
+
+ /* Set the XferSize to transfer */
+ if (hi2c->XferCount > MAX_NBYTE_SIZE)
+ {
+ hi2c->XferSize = MAX_NBYTE_SIZE;
+ }
+ else
+ {
+ hi2c->XferSize = hi2c->XferCount;
+ }
+
+ /* Enable the DMA stream or channel depends on Instance */
+ if (HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr,
+ hi2c->XferSize) != HAL_OK)
+ {
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
+ }
+ else
+ {
+ /* Enable TC interrupts */
+ I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT);
+ }
+ }
+}
+
+
+/**
+ * @brief DMA I2C slave receive process complete callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+ uint32_t tmpoptions = hi2c->XferOptions;
+
+ if ((I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx) == 0U) && \
+ (tmpoptions != I2C_NO_OPTION_FRAME))
+ {
+ /* Disable DMA Request */
+ hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN;
+
+ /* Call I2C Slave Sequential complete process */
+ I2C_ITSlaveSeqCplt(hi2c);
+ }
+ else
+ {
+ /* No specific action, Master fully manage the generation of STOP condition */
+ /* Mean that this generation can arrive at any time, at the end or during DMA process */
+ /* So STOP condition should be manage through Interrupt treatment */
+ }
+}
+
+
+/**
+ * @brief DMA I2C communication error callback.
+ * @param hdma DMA handle
+ * @retval None
+ */
+static void I2C_DMAError(DMA_HandleTypeDef *hdma)
+{
+ uint32_t treatdmaerror = 0U;
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ if (hi2c->hdmatx != NULL)
+ {
+ if (I2C_GET_DMA_REMAIN_DATA(hi2c->hdmatx) == 0U)
+ {
+ treatdmaerror = 1U;
+ }
+ }
+
+ if (hi2c->hdmarx != NULL)
+ {
+ if (I2C_GET_DMA_REMAIN_DATA(hi2c->hdmarx) == 0U)
+ {
+ treatdmaerror = 1U;
+ }
+ }
+
+ /* Check if a FIFO error is detected, if true normal use case, so no specific action to perform */
+ if (!((HAL_DMA_GetError(hdma) == HAL_DMA_ERROR_FE)) && (treatdmaerror != 0U))
+ {
+ /* Disable Acknowledge */
+ hi2c->Instance->CR2 |= I2C_CR2_NACK;
+
+ /* Call the corresponding callback to inform upper layer of End of Transfer */
+ I2C_ITError(hi2c, HAL_I2C_ERROR_DMA);
+ }
+}
+
+
+/**
+ * @brief DMA I2C communication abort callback
+ * (To be called at end of DMA Abort procedure).
+ * @param hdma DMA handle.
+ * @retval None
+ */
+static void I2C_DMAAbort(DMA_HandleTypeDef *hdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
+
+ /* Reset AbortCpltCallback */
+ if (hi2c->hdmatx != NULL)
+ {
+ hi2c->hdmatx->XferAbortCallback = NULL;
+ }
+ if (hi2c->hdmarx != NULL)
+ {
+ hi2c->hdmarx->XferAbortCallback = NULL;
+ }
+
+ I2C_TreatErrorCallback(hi2c);
+}
+
+
+/**
+ * @brief This function handles I2C Communication Timeout. It waits
+ * until a flag is no longer in the specified status.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Flag Specifies the I2C flag to check.
+ * @param Status The actual Flag status (SET or RESET).
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status,
+ uint32_t Timeout, uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of TXIS flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of STOP flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check for the Timeout */
+ if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout,
+ uint32_t Tickstart)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ while ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) && (status == HAL_OK))
+ {
+ /* Check if an error is detected */
+ if (I2C_IsErrorOccurred(hi2c, Timeout, Tickstart) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Check if a STOPF is detected */
+ if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) && (status == HAL_OK))
+ {
+ /* Check if an RXNE is pending */
+ /* Store Last receive data if any */
+ if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) && (hi2c->XferSize > 0U))
+ {
+ /* Return HAL_OK */
+ /* The Reading of data from RXDR will be done in caller function */
+ status = HAL_OK;
+ }
+
+ /* Check a no-acknowledge have been detected */
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET)
+ {
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+ hi2c->ErrorCode = HAL_I2C_ERROR_AF;
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ status = HAL_ERROR;
+ }
+ else
+ {
+ hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
+ }
+ }
+
+ /* Check for the Timeout */
+ if ((((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) && (status == HAL_OK))
+ {
+ if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)
+ {
+ hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT;
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ status = HAL_ERROR;
+ }
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief This function handles errors detection during an I2C Communication.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param Timeout Timeout duration
+ * @param Tickstart Tick start value
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef I2C_IsErrorOccurred(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t itflag = hi2c->Instance->ISR;
+ uint32_t error_code = 0;
+ uint32_t tickstart = Tickstart;
+ uint32_t tmp1;
+ HAL_I2C_ModeTypeDef tmp2;
+
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_AF))
+ {
+ /* Clear NACKF Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);
+
+ /* Wait until STOP Flag is set or timeout occurred */
+ /* AutoEnd should be initiate after AF */
+ while ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) && (status == HAL_OK))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ tmp1 = (uint32_t)(hi2c->Instance->CR2 & I2C_CR2_STOP);
+ tmp2 = hi2c->Mode;
+
+ /* In case of I2C still busy, try to regenerate a STOP manually */
+ if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET) && \
+ (tmp1 != I2C_CR2_STOP) && \
+ (tmp2 != HAL_I2C_MODE_SLAVE))
+ {
+ /* Generate Stop */
+ hi2c->Instance->CR2 |= I2C_CR2_STOP;
+
+ /* Update Tick with new reference */
+ tickstart = HAL_GetTick();
+ }
+
+ while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > I2C_TIMEOUT_STOPF)
+ {
+ error_code |= HAL_I2C_ERROR_TIMEOUT;
+
+ status = HAL_ERROR;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* In case STOP Flag is detected, clear it */
+ if (status == HAL_OK)
+ {
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);
+ }
+
+ error_code |= HAL_I2C_ERROR_AF;
+
+ status = HAL_ERROR;
+ }
+
+ /* Refresh Content of Status register */
+ itflag = hi2c->Instance->ISR;
+
+ /* Then verify if an additional errors occurs */
+ /* Check if a Bus error occurred */
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_BERR))
+ {
+ error_code |= HAL_I2C_ERROR_BERR;
+
+ /* Clear BERR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
+
+ status = HAL_ERROR;
+ }
+
+ /* Check if an Over-Run/Under-Run error occurred */
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_OVR))
+ {
+ error_code |= HAL_I2C_ERROR_OVR;
+
+ /* Clear OVR flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
+
+ status = HAL_ERROR;
+ }
+
+ /* Check if an Arbitration Loss error occurred */
+ if (HAL_IS_BIT_SET(itflag, I2C_FLAG_ARLO))
+ {
+ error_code |= HAL_I2C_ERROR_ARLO;
+
+ /* Clear ARLO flag */
+ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
+
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_OK)
+ {
+ /* Flush TX register */
+ I2C_Flush_TXDR(hi2c);
+
+ /* Clear Configuration Register 2 */
+ I2C_RESET_CR2(hi2c);
+
+ hi2c->ErrorCode |= error_code;
+ hi2c->State = HAL_I2C_STATE_READY;
+ hi2c->Mode = HAL_I2C_MODE_NONE;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
+ * @param hi2c I2C handle.
+ * @param DevAddress Specifies the slave address to be programmed.
+ * @param Size Specifies the number of bytes to be programmed.
+ * This parameter must be a value between 0 and 255.
+ * @param Mode New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_RELOAD_MODE Enable Reload mode .
+ * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
+ * @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
+ * @param Request New state of the I2C START condition generation.
+ * This parameter can be one of the following values:
+ * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
+ * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
+ * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
+ * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
+ * @retval None
+ */
+static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
+ uint32_t Request)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_TRANSFER_MODE(Mode));
+ assert_param(IS_TRANSFER_REQUEST(Request));
+
+ /* Declaration of tmp to prevent undefined behavior of volatile usage */
+ tmp = ((uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | \
+ (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | \
+ (uint32_t)Mode | (uint32_t)Request) & (~0x80000000U));
+
+ /* update CR2 register */
+ MODIFY_REG(hi2c->Instance->CR2, \
+ ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | \
+ (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | \
+ I2C_CR2_START | I2C_CR2_STOP)), tmp);
+}
+
+/**
+ * @brief Manage the enabling of Interrupts.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition.
+ * @retval None
+ */
+static void I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest)
+{
+ uint32_t tmpisr = 0U;
+
+ if ((hi2c->XferISR != I2C_Master_ISR_DMA) && \
+ (hi2c->XferISR != I2C_Slave_ISR_DMA) && \
+ (hi2c->XferISR != I2C_Mem_ISR_DMA))
+ {
+ if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Enable ERR, STOP, NACK and ADDR interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and TXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and RXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI;
+ }
+
+ if (InterruptRequest == I2C_XFER_ERROR_IT)
+ {
+ /* Enable ERR and NACK interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= I2C_IT_STOPI;
+ }
+ }
+
+ else
+ {
+ if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Enable ERR, STOP, NACK and ADDR interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and TXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI;
+ }
+
+ if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Enable ERR, TC, STOP, NACK and RXI interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI;
+ }
+
+ if (InterruptRequest == I2C_XFER_ERROR_IT)
+ {
+ /* Enable ERR and NACK interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= (I2C_IT_STOPI | I2C_IT_TCI);
+ }
+
+ if (InterruptRequest == I2C_XFER_RELOAD_IT)
+ {
+ /* Enable TC interrupts */
+ tmpisr |= I2C_IT_TCI;
+ }
+ }
+
+ /* Enable interrupts only at the end */
+ /* to avoid the risk of I2C interrupt handle execution before */
+ /* all interrupts requested done */
+ __HAL_I2C_ENABLE_IT(hi2c, tmpisr);
+}
+
+/**
+ * @brief Manage the disabling of Interrupts.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2C.
+ * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition.
+ * @retval None
+ */
+static void I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest)
+{
+ uint32_t tmpisr = 0U;
+
+ if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT)
+ {
+ /* Disable TC and TXI interrupts */
+ tmpisr |= I2C_IT_TCI | I2C_IT_TXI;
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) != (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ /* Disable NACK and STOP interrupts */
+ tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+ }
+
+ if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT)
+ {
+ /* Disable TC and RXI interrupts */
+ tmpisr |= I2C_IT_TCI | I2C_IT_RXI;
+
+ if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) != (uint32_t)HAL_I2C_STATE_LISTEN)
+ {
+ /* Disable NACK and STOP interrupts */
+ tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+ }
+
+ if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT)
+ {
+ /* Disable ADDR, NACK and STOP interrupts */
+ tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI;
+ }
+
+ if (InterruptRequest == I2C_XFER_ERROR_IT)
+ {
+ /* Enable ERR and NACK interrupts */
+ tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI;
+ }
+
+ if (InterruptRequest == I2C_XFER_CPLT_IT)
+ {
+ /* Enable STOP interrupts */
+ tmpisr |= I2C_IT_STOPI;
+ }
+
+ if (InterruptRequest == I2C_XFER_RELOAD_IT)
+ {
+ /* Enable TC interrupts */
+ tmpisr |= I2C_IT_TCI;
+ }
+
+ /* Disable interrupts only at the end */
+ /* to avoid a breaking situation like at "t" time */
+ /* all disable interrupts request are not done */
+ __HAL_I2C_DISABLE_IT(hi2c, tmpisr);
+}
+
+/**
+ * @brief Convert I2Cx OTHER_xxx XferOptions to functional XferOptions.
+ * @param hi2c I2C handle.
+ * @retval None
+ */
+static void I2C_ConvertOtherXferOptions(I2C_HandleTypeDef *hi2c)
+{
+ /* if user set XferOptions to I2C_OTHER_FRAME */
+ /* it request implicitly to generate a restart condition */
+ /* set XferOptions to I2C_FIRST_FRAME */
+ if (hi2c->XferOptions == I2C_OTHER_FRAME)
+ {
+ hi2c->XferOptions = I2C_FIRST_FRAME;
+ }
+ /* else if user set XferOptions to I2C_OTHER_AND_LAST_FRAME */
+ /* it request implicitly to generate a restart condition */
+ /* then generate a stop condition at the end of transfer */
+ /* set XferOptions to I2C_FIRST_AND_LAST_FRAME */
+ else if (hi2c->XferOptions == I2C_OTHER_AND_LAST_FRAME)
+ {
+ hi2c->XferOptions = I2C_FIRST_AND_LAST_FRAME;
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c
new file mode 100755
index 0000000..d9b8e46
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_i2c_ex.c
@@ -0,0 +1,372 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_i2c_ex.c
+ * @author MCD Application Team
+ * @brief I2C Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of I2C Extended peripheral:
+ * + Filter Mode Functions
+ * + WakeUp Mode Functions
+ * + FastModePlus Functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### I2C peripheral Extended features #####
+ ==============================================================================
+
+ [..] Comparing to other previous devices, the I2C interface for STM32H7xx
+ devices contains the following additional features
+
+ (+) Possibility to disable or enable Analog Noise Filter
+ (+) Use of a configured Digital Noise Filter
+ (+) Disable or enable wakeup from Stop mode(s)
+ (+) Disable or enable Fast Mode Plus
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..] This driver provides functions to configure Noise Filter and Wake Up Feature
+ (#) Configure I2C Analog noise filter using the function HAL_I2CEx_ConfigAnalogFilter()
+ (#) Configure I2C Digital noise filter using the function HAL_I2CEx_ConfigDigitalFilter()
+ (#) Configure the enable or disable of I2C Wake Up Mode using the functions :
+ (++) HAL_I2CEx_EnableWakeUp()
+ (++) HAL_I2CEx_DisableWakeUp()
+ (#) Configure the enable or disable of fast mode plus driving capability using the functions :
+ (++) HAL_I2CEx_EnableFastModePlus()
+ (++) HAL_I2CEx_DisableFastModePlus()
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup I2CEx I2CEx
+ * @brief I2C Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_I2C_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup I2CEx_Exported_Functions I2C Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group1 Filter Mode Functions
+ * @brief Filter Mode Functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Filter Mode Functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Noise Filters
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure I2C Analog noise filter.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @param AnalogFilter New state of the Analog filter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Reset I2Cx ANOFF bit */
+ hi2c->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
+
+ /* Set analog filter bit*/
+ hi2c->Instance->CR1 |= AnalogFilter;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Configure I2C Digital noise filter.
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
+ assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Get the old register value */
+ tmpreg = hi2c->Instance->CR1;
+
+ /* Reset I2Cx DNF bits [11:8] */
+ tmpreg &= ~(I2C_CR1_DNF);
+
+ /* Set I2Cx DNF coefficient */
+ tmpreg |= DigitalFilter << 8U;
+
+ /* Store the new register value */
+ hi2c->Instance->CR1 = tmpreg;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group2 WakeUp Mode Functions
+ * @brief WakeUp Mode Functions
+ *
+@verbatim
+ ===============================================================================
+ ##### WakeUp Mode Functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Wake Up Feature
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable I2C wakeup from Stop mode(s).
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Enable wakeup from stop mode */
+ hi2c->Instance->CR1 |= I2C_CR1_WUPEN;
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disable I2C wakeup from Stop mode(s).
+ * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
+ * the configuration information for the specified I2Cx peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c)
+{
+ /* Check the parameters */
+ assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance));
+
+ if (hi2c->State == HAL_I2C_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_BUSY;
+
+ /* Disable the selected I2C peripheral */
+ __HAL_I2C_DISABLE(hi2c);
+
+ /* Enable wakeup from stop mode */
+ hi2c->Instance->CR1 &= ~(I2C_CR1_WUPEN);
+
+ __HAL_I2C_ENABLE(hi2c);
+
+ hi2c->State = HAL_I2C_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hi2c);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+/**
+ * @}
+ */
+
+/** @defgroup I2CEx_Exported_Functions_Group3 Fast Mode Plus Functions
+ * @brief Fast Mode Plus Functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Fast Mode Plus Functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure Fast Mode Plus
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the I2C fast mode plus driving capability.
+ * @param ConfigFastModePlus Selects the pin.
+ * This parameter can be one of the @ref I2CEx_FastModePlus values
+ * @note For I2C1, fast mode plus driving capability can be enabled on all selected
+ * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
+ * on each one of the following pins PB6, PB7, PB8 and PB9.
+ * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
+ * can be enabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
+ * @note For all I2C2 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C2 parameter.
+ * @note For all I2C3 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C3 parameter.
+ * @note For all I2C4 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C4 parameter.
+ * @note For all I2C5 pins fast mode plus driving capability can be enabled
+ * only by using I2C_FASTMODEPLUS_I2C5 parameter.
+ * @retval None
+ */
+void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus)
+{
+ /* Check the parameter */
+ assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
+
+ /* Enable SYSCFG clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ /* Enable fast mode plus driving capability for selected pin */
+ SET_BIT(SYSCFG->PMCR, (uint32_t)ConfigFastModePlus);
+}
+
+/**
+ * @brief Disable the I2C fast mode plus driving capability.
+ * @param ConfigFastModePlus Selects the pin.
+ * This parameter can be one of the @ref I2CEx_FastModePlus values
+ * @note For I2C1, fast mode plus driving capability can be disabled on all selected
+ * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
+ * on each one of the following pins PB6, PB7, PB8 and PB9.
+ * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
+ * can be disabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
+ * @note For all I2C2 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C2 parameter.
+ * @note For all I2C3 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C3 parameter.
+ * @note For all I2C4 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C4 parameter.
+ * @note For all I2C5 pins fast mode plus driving capability can be disabled
+ * only by using I2C_FASTMODEPLUS_I2C5 parameter.
+ * @retval None
+ */
+void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus)
+{
+ /* Check the parameter */
+ assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
+
+ /* Enable SYSCFG clock */
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+
+ /* Disable fast mode plus driving capability for selected pin */
+ CLEAR_BIT(SYSCFG->PMCR, (uint32_t)ConfigFastModePlus);
+}
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+
+#endif /* HAL_I2C_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c
new file mode 100755
index 0000000..064949b
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_mdma.c
@@ -0,0 +1,1899 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_mdma.c
+ * @author MCD Application Team
+ * @brief This file provides firmware functions to manage the following
+ * functionalities of the Master Direct Memory Access (MDMA) peripheral:
+ * + Initialization/de-initialization functions
+ * + I/O operation functions
+ * + Peripheral State and errors functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Enable and configure the peripheral to be connected to the MDMA Channel
+ (except for internal SRAM/FLASH memories: no initialization is
+ necessary) please refer to Reference manual for connection between peripherals
+ and MDMA requests.
+
+ (#)
+ For a given Channel use HAL_MDMA_Init function to program the required configuration through the following parameters:
+ transfer request , channel priority, data endianness, Source increment, destination increment ,
+ source data size, destination data size, data alignment, source Burst, destination Burst ,
+ buffer Transfer Length, Transfer Trigger Mode (buffer transfer, block transfer, repeated block transfer
+ or full transfer) source and destination block address offset, mask address and data.
+
+ If using the MDMA in linked list mode then use function HAL_MDMA_LinkedList_CreateNode to fill a transfer node.
+ Note that parameters given to the function HAL_MDMA_Init corresponds always to the node zero.
+ Use function HAL_MDMA_LinkedList_AddNode to connect the created node to the linked list at a given position.
+ User can make a linked list circular using function HAL_MDMA_LinkedList_EnableCircularMode , this function will automatically connect the
+ last node of the list to the first one in order to make the list circular.
+ In this case the linked list will loop on node 1 : first node connected after the initial transfer defined by the HAL_MDMA_Init
+
+ -@- The initial transfer itself (node 0 corresponding to the Init).
+ User can disable the circular mode using function HAL_MDMA_LinkedList_DisableCircularMode, this function will then remove
+ the connection between last node and first one.
+
+ Function HAL_MDMA_LinkedList_RemoveNode can be used to remove (disconnect) a node from the transfer linked list.
+ When a linked list is circular (last node connected to first one), if removing node1 (node where the linked list loops),
+ the linked list remains circular and node 2 becomes the first one.
+ Note that if the linked list is made circular the transfer will loop infinitely (or until aborted by the user).
+
+ [..]
+ (+) User can select the transfer trigger mode (parameter TransferTriggerMode) to define the amount of data to be
+ transfer upon a request :
+ (++) MDMA_BUFFER_TRANSFER : each request triggers a transfer of BufferTransferLength data
+ with BufferTransferLength defined within the HAL_MDMA_Init.
+ (++) MDMA_BLOCK_TRANSFER : each request triggers a transfer of a block
+ with block size defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
+ or within the current linked list node parameters.
+ (++) MDMA_REPEAT_BLOCK_TRANSFER : each request triggers a transfer of a number of blocks
+ with block size and number of blocks defined within the function HAL_MDMA_Start/HAL_MDMA_Start_IT
+ or within the current linked list node parameters.
+ (++) MDMA_FULL_TRANSFER : each request triggers a full transfer
+ all blocks and all nodes(if a linked list has been created using HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode).
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Use HAL_MDMA_Start() to start MDMA transfer after the configuration of Source
+ address and destination address and the Length of data to be transferred.
+ (+) Use HAL_MDMA_PollForTransfer() to poll for the end of current transfer or a transfer level
+ In this case a fixed Timeout can be configured by User depending from his application.
+ (+) Use HAL_MDMA_Abort() function to abort the current transfer : blocking method this API returns
+ when the abort ends or timeout (should not be called from an interrupt service routine).
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Configure the MDMA interrupt priority using HAL_NVIC_SetPriority()
+ (+) Enable the MDMA IRQ handler using HAL_NVIC_EnableIRQ()
+ (+) Use HAL_MDMA_Start_IT() to start MDMA transfer after the configuration of
+ Source address and destination address and the Length of data to be transferred. In this
+ case the MDMA interrupt is configured.
+ (+) Use HAL_MDMA_IRQHandler() called under MDMA_IRQHandler() Interrupt subroutine
+ (+) At the end of data transfer HAL_MDMA_IRQHandler() function is executed and user can
+ add his own function by customization of function pointer XferCpltCallback and
+ XferErrorCallback (i.e a member of MDMA handle structure).
+
+ (+) Use HAL_MDMA_Abort_IT() function to abort the current transfer : non-blocking method. This API will finish the execution immediately
+ then the callback XferAbortCallback (if specified by the user) is asserted once the MDMA channel has effectively aborted.
+ (could be called from an interrupt service routine).
+
+ (+) Use functions HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback respectevely to register unregister user callbacks
+ from the following list :
+ (++) XferCpltCallback : transfer complete callback.
+ (++) XferBufferCpltCallback : buffer transfer complete callback.
+ (++) XferBlockCpltCallback : block transfer complete callback.
+ (++) XferRepeatBlockCpltCallback : repeated block transfer complete callback.
+ (++) XferErrorCallback : transfer error callback.
+ (++) XferAbortCallback : transfer abort complete callback.
+
+ [..]
+ (+) If the transfer Request corresponds to SW request (MDMA_REQUEST_SW) User can use function HAL_MDMA_GenerateSWRequest to
+ trigger requests manually. Function HAL_MDMA_GenerateSWRequest must be used with the following precautions:
+ (++) This function returns an error if used while the Transfer has ended or not started.
+ (++) If used while the current request has not been served yet (current request transfer on going)
+ this function returns an error and the new request is ignored.
+
+ Generally this function should be used in conjunctions with the MDMA callbacks:
+ (++) example 1:
+ (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BUFFER_TRANSFER
+ (+++) Register a callback for buffer transfer complete (using callback ID set to HAL_MDMA_XFER_BUFFERCPLT_CB_ID)
+ (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first BufferTransferLength data.
+ (+++) When the buffer transfer complete callback is asserted first buffer has been transferred and user can ask for a new buffer transfer
+ request using HAL_MDMA_GenerateSWRequest.
+
+ (++) example 2:
+ (+++) Configure a transfer with request set to MDMA_REQUEST_SW and trigger mode set to MDMA_BLOCK_TRANSFER
+ (+++) Register a callback for block transfer complete (using callback ID HAL_MDMA_XFER_BLOCKCPLT_CB_ID)
+ (+++) After calling HAL_MDMA_Start_IT the MDMA will issue the transfer of a first block of data.
+ (+++) When the block transfer complete callback is asserted the first block has been transferred and user can ask
+ for a new block transfer request using HAL_MDMA_GenerateSWRequest.
+
+ [..] Use HAL_MDMA_GetState() function to return the MDMA state and HAL_MDMA_GetError() in case of error detection.
+
+ *** MDMA HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in MDMA HAL driver.
+
+ (+) __HAL_MDMA_ENABLE: Enable the specified MDMA Channel.
+ (+) __HAL_MDMA_DISABLE: Disable the specified MDMA Channel.
+ (+) __HAL_MDMA_GET_FLAG: Get the MDMA Channel pending flags.
+ (+) __HAL_MDMA_CLEAR_FLAG: Clear the MDMA Channel pending flags.
+ (+) __HAL_MDMA_ENABLE_IT: Enable the specified MDMA Channel interrupts.
+ (+) __HAL_MDMA_DISABLE_IT: Disable the specified MDMA Channel interrupts.
+ (+) __HAL_MDMA_GET_IT_SOURCE: Check whether the specified MDMA Channel interrupt has occurred or not.
+
+ [..]
+ (@) You can refer to the header file of the MDMA HAL driver for more useful macros.
+
+ [..]
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup MDMA MDMA
+ * @brief MDMA HAL module driver
+ * @{
+ */
+
+#ifdef HAL_MDMA_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+/** @addtogroup MDMA_Private_Constants
+ * @{
+ */
+#define HAL_TIMEOUT_MDMA_ABORT 5U /* 5 ms */
+#define HAL_MDMA_CHANNEL_SIZE 0x40U /* an MDMA instance channel size is 64 byte */
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup MDMA_Private_Functions_Prototypes
+ * @{
+ */
+static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount);
+static void MDMA_Init(MDMA_HandleTypeDef *hmdma);
+
+/**
+ * @}
+ */
+
+/** @addtogroup MDMA_Exported_Functions MDMA Exported Functions
+ * @{
+ */
+
+/** @addtogroup MDMA_Exported_Functions_Group1
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to :
+ Initialize and de-initialize the MDMA channel.
+ Register and Unregister MDMA callbacks
+ [..]
+ The HAL_MDMA_Init() function follows the MDMA channel configuration procedures as described in
+ reference manual.
+ The HAL_MDMA_DeInit function allows to deinitialize the MDMA channel.
+ HAL_MDMA_RegisterCallback and HAL_MDMA_UnRegisterCallback functions allows
+ respectevely to register/unregister an MDMA callback function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the MDMA according to the specified
+ * parameters in the MDMA_InitTypeDef and create the associated handle.
+ * @param hmdma: Pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
+ assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
+ assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));
+ assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
+ assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
+ assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
+ assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
+ assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
+ assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
+ assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
+ assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
+ assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));
+ assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
+ assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
+ assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
+
+
+ /* Allocate lock resource */
+ __HAL_UNLOCK(hmdma);
+
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Check if the MDMA channel is effectively disabled */
+ while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
+ {
+ /* Check for the Timeout */
+ if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
+ {
+ /* Update error code */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;
+
+ /* Change the MDMA state */
+ hmdma->State = HAL_MDMA_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Initialize the MDMA channel registers */
+ MDMA_Init(hmdma);
+
+ /* Reset the MDMA first/last linkedlist node addresses and node counter */
+ hmdma->FirstLinkedListNodeAddress = 0;
+ hmdma->LastLinkedListNodeAddress = 0;
+ hmdma->LinkedListNodeCounter = 0;
+
+ /* Initialize the error code */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
+
+ /* Initialize the MDMA state */
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the MDMA peripheral
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_DeInit(MDMA_HandleTypeDef *hmdma)
+{
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the selected MDMA Channelx */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Reset MDMA Channel control register */
+ hmdma->Instance->CCR = 0;
+ hmdma->Instance->CTCR = 0;
+ hmdma->Instance->CBNDTR = 0;
+ hmdma->Instance->CSAR = 0;
+ hmdma->Instance->CDAR = 0;
+ hmdma->Instance->CBRUR = 0;
+ hmdma->Instance->CLAR = 0;
+ hmdma->Instance->CTBR = 0;
+ hmdma->Instance->CMAR = 0;
+ hmdma->Instance->CMDR = 0;
+
+ /* Clear all flags */
+ __HAL_MDMA_CLEAR_FLAG(hmdma,(MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC));
+
+ /* Reset the MDMA first/last linkedlist node addresses and node counter */
+ hmdma->FirstLinkedListNodeAddress = 0;
+ hmdma->LastLinkedListNodeAddress = 0;
+ hmdma->LinkedListNodeCounter = 0;
+
+ /* Initialize the error code */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
+
+ /* Initialize the MDMA state */
+ hmdma->State = HAL_MDMA_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdma);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Config the Post request Mask address and Mask data
+ * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param MaskAddress: specifies the address to be updated (written) with MaskData after a request is served.
+ * @param MaskData: specifies the value to be written to MaskAddress after a request is served.
+ * MaskAddress and MaskData could be used to automatically clear a peripheral flag when the request is served.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_ConfigPostRequestMask(MDMA_HandleTypeDef *hmdma, uint32_t MaskAddress, uint32_t MaskData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* if HW request set Post Request MaskAddress and MaskData, */
+ if((hmdma->Instance->CTCR & MDMA_CTCR_SWRM) == 0U)
+ {
+ /* Set the HW request clear Mask and Data */
+ hmdma->Instance->CMAR = MaskAddress;
+ hmdma->Instance->CMDR = MaskData;
+
+ /*
+ -If the request is done by SW : BWM could be set to 1 or 0.
+ -If the request is done by a peripheral :
+ If mask address not set (0) => BWM must be set to 0
+ If mask address set (different than 0) => BWM could be set to 1 or 0
+ */
+ if(MaskAddress == 0U)
+ {
+ hmdma->Instance->CTCR &= ~MDMA_CTCR_BWM;
+ }
+ else
+ {
+ hmdma->Instance->CTCR |= MDMA_CTCR_BWM;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+ /* Release Lock */
+ __HAL_UNLOCK(hmdma);
+
+ return status;
+}
+
+/**
+ * @brief Register callbacks
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param CallbackID: User Callback identifier
+ * @param pCallback: pointer to callbacsk function.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_RegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID, void (* pCallback)(MDMA_HandleTypeDef *_hmdma))
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_MDMA_XFER_CPLT_CB_ID:
+ hmdma->XferCpltCallback = pCallback;
+ break;
+
+ case HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
+ hmdma->XferBufferCpltCallback = pCallback;
+ break;
+
+ case HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
+ hmdma->XferBlockCpltCallback = pCallback;
+ break;
+
+ case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
+ hmdma->XferRepeatBlockCpltCallback = pCallback;
+ break;
+
+ case HAL_MDMA_XFER_ERROR_CB_ID:
+ hmdma->XferErrorCallback = pCallback;
+ break;
+
+ case HAL_MDMA_XFER_ABORT_CB_ID:
+ hmdma->XferAbortCallback = pCallback;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdma);
+
+ return status;
+}
+
+/**
+ * @brief UnRegister callbacks
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param CallbackID: User Callback identifier
+ * a HAL_MDMA_CallbackIDTypeDef ENUM as parameter.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_UnRegisterCallback(MDMA_HandleTypeDef *hmdma, HAL_MDMA_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_MDMA_XFER_CPLT_CB_ID:
+ hmdma->XferCpltCallback = NULL;
+ break;
+
+ case HAL_MDMA_XFER_BUFFERCPLT_CB_ID:
+ hmdma->XferBufferCpltCallback = NULL;
+ break;
+
+ case HAL_MDMA_XFER_BLOCKCPLT_CB_ID:
+ hmdma->XferBlockCpltCallback = NULL;
+ break;
+
+ case HAL_MDMA_XFER_REPBLOCKCPLT_CB_ID:
+ hmdma->XferRepeatBlockCpltCallback = NULL;
+ break;
+
+ case HAL_MDMA_XFER_ERROR_CB_ID:
+ hmdma->XferErrorCallback = NULL;
+ break;
+
+ case HAL_MDMA_XFER_ABORT_CB_ID:
+ hmdma->XferAbortCallback = NULL;
+ break;
+
+ case HAL_MDMA_XFER_ALL_CB_ID:
+ hmdma->XferCpltCallback = NULL;
+ hmdma->XferBufferCpltCallback = NULL;
+ hmdma->XferBlockCpltCallback = NULL;
+ hmdma->XferRepeatBlockCpltCallback = NULL;
+ hmdma->XferErrorCallback = NULL;
+ hmdma->XferAbortCallback = NULL;
+ break;
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hmdma);
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup MDMA_Exported_Functions_Group2
+ *
+@verbatim
+ ===============================================================================
+ ##### Linked list operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Create a linked list node
+ (+) Add a node to the MDMA linked list
+ (+) Remove a node from the MDMA linked list
+ (+) Enable/Disable linked list circular mode
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes an MDMA Link Node according to the specified
+ * parameters in the pMDMA_LinkedListNodeConfig .
+ * @param pNode: Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
+ * registers configurations.
+ * @param pNodeConfig: Pointer to a MDMA_LinkNodeConfTypeDef structure that contains
+ * the configuration information for the specified MDMA Linked List Node.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_LinkedList_CreateNode(MDMA_LinkNodeTypeDef *pNode, MDMA_LinkNodeConfTypeDef *pNodeConfig)
+{
+ uint32_t addressMask;
+ uint32_t blockoffset;
+
+ /* Check the MDMA peripheral state */
+ if((pNode == NULL) || (pNodeConfig == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_MDMA_PRIORITY(pNodeConfig->Init.Priority));
+ assert_param(IS_MDMA_ENDIANNESS_MODE(pNodeConfig->Init.Endianness));
+ assert_param(IS_MDMA_REQUEST(pNodeConfig->Init.Request));
+ assert_param(IS_MDMA_SOURCE_INC(pNodeConfig->Init.SourceInc));
+ assert_param(IS_MDMA_DESTINATION_INC(pNodeConfig->Init.DestinationInc));
+ assert_param(IS_MDMA_SOURCE_DATASIZE(pNodeConfig->Init.SourceDataSize));
+ assert_param(IS_MDMA_DESTINATION_DATASIZE(pNodeConfig->Init.DestDataSize));
+ assert_param(IS_MDMA_DATA_ALIGNMENT(pNodeConfig->Init.DataAlignment));
+ assert_param(IS_MDMA_SOURCE_BURST(pNodeConfig->Init.SourceBurst));
+ assert_param(IS_MDMA_DESTINATION_BURST(pNodeConfig->Init.DestBurst));
+ assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(pNodeConfig->Init.BufferTransferLength));
+ assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(pNodeConfig->Init.TransferTriggerMode));
+ assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.SourceBlockAddressOffset));
+ assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(pNodeConfig->Init.DestBlockAddressOffset));
+
+ assert_param(IS_MDMA_TRANSFER_LENGTH(pNodeConfig->BlockDataLength));
+ assert_param(IS_MDMA_BLOCK_COUNT(pNodeConfig->BlockCount));
+
+
+ /* Configure next Link node Address Register to zero */
+ pNode->CLAR = 0;
+
+ /* Configure the Link Node registers*/
+ pNode->CTBR = 0;
+ pNode->CMAR = 0;
+ pNode->CMDR = 0;
+ pNode->Reserved = 0;
+
+ /* Write new CTCR Register value */
+ pNode->CTCR = pNodeConfig->Init.SourceInc | pNodeConfig->Init.DestinationInc | \
+ pNodeConfig->Init.SourceDataSize | pNodeConfig->Init.DestDataSize | \
+ pNodeConfig->Init.DataAlignment| pNodeConfig->Init.SourceBurst | \
+ pNodeConfig->Init.DestBurst | \
+ ((pNodeConfig->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
+ pNodeConfig->Init.TransferTriggerMode;
+
+ /* If SW request set the CTCR register to SW Request Mode*/
+ if(pNodeConfig->Init.Request == MDMA_REQUEST_SW)
+ {
+ pNode->CTCR |= MDMA_CTCR_SWRM;
+ }
+
+ /*
+ -If the request is done by SW : BWM could be set to 1 or 0.
+ -If the request is done by a peripheral :
+ If mask address not set (0) => BWM must be set to 0
+ If mask address set (different than 0) => BWM could be set to 1 or 0
+ */
+ if((pNodeConfig->Init.Request == MDMA_REQUEST_SW) || (pNodeConfig->PostRequestMaskAddress != 0U))
+ {
+ pNode->CTCR |= MDMA_CTCR_BWM;
+ }
+
+ /* Set the new CBNDTR Register value */
+ pNode->CBNDTR = ((pNodeConfig->BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC;
+
+ /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
+ if(pNodeConfig->Init.SourceBlockAddressOffset < 0)
+ {
+ pNode->CBNDTR |= MDMA_CBNDTR_BRSUM;
+ /*write new CBRUR Register value : source repeat block offset */
+ blockoffset = (uint32_t)(- pNodeConfig->Init.SourceBlockAddressOffset);
+ pNode->CBRUR = blockoffset & 0x0000FFFFU;
+ }
+ else
+ {
+ /*write new CBRUR Register value : source repeat block offset */
+ pNode->CBRUR = (((uint32_t) pNodeConfig->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
+ }
+
+ /* if block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
+ if(pNodeConfig->Init.DestBlockAddressOffset < 0)
+ {
+ pNode->CBNDTR |= MDMA_CBNDTR_BRDUM;
+ /*write new CBRUR Register value : destination repeat block offset */
+ blockoffset = (uint32_t)(- pNodeConfig->Init.DestBlockAddressOffset);
+ pNode->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
+ }
+ else
+ {
+ /*write new CBRUR Register value : destination repeat block offset */
+ pNode->CBRUR |= ((((uint32_t)pNodeConfig->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
+ }
+
+ /* Configure MDMA Link Node data length */
+ pNode->CBNDTR |= pNodeConfig->BlockDataLength;
+
+ /* Configure MDMA Link Node destination address */
+ pNode->CDAR = pNodeConfig->DstAddress;
+
+ /* Configure MDMA Link Node Source address */
+ pNode->CSAR = pNodeConfig->SrcAddress;
+
+ /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
+ if(pNodeConfig->Init.Request != MDMA_REQUEST_SW)
+ {
+ /* Set the HW request in CTBR register */
+ pNode->CTBR = pNodeConfig->Init.Request & MDMA_CTBR_TSEL;
+ /* Set the HW request clear Mask and Data */
+ pNode->CMAR = pNodeConfig->PostRequestMaskAddress;
+ pNode->CMDR = pNodeConfig->PostRequestMaskData;
+ }
+
+ addressMask = pNodeConfig->SrcAddress & 0xFF000000U;
+ if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
+ {
+ /*The AHBSbus is used as source (read operation) on channel x */
+ pNode->CTBR |= MDMA_CTBR_SBUS;
+ }
+
+ addressMask = pNodeConfig->DstAddress & 0xFF000000U;
+ if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
+ {
+ /*The AHB bus is used as destination (write operation) on channel x */
+ pNode->CTBR |= MDMA_CTBR_DBUS;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Connect a node to the linked list.
+ * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param pNewNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
+ * to be add to the list.
+ * @param pPrevNode : Pointer to the new node position in the linked list or zero to insert the new node
+ * at the end of the list
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_LinkedList_AddNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNewNode, const MDMA_LinkNodeTypeDef *pPrevNode)
+{
+ MDMA_LinkNodeTypeDef *pNode;
+ uint32_t counter = 0, nodeInserted = 0;
+ HAL_StatusTypeDef hal_status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if((hmdma == NULL) || (pNewNode == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* Check if this is the first node (after the Inititlization node) */
+ if((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U)
+ {
+ if(pPrevNode == NULL)
+ {
+ /* if this is the first node after the initialization
+ connect this node to the node 0 by updating
+ the MDMA channel CLAR register to this node address */
+ hmdma->Instance->CLAR = (uint32_t)pNewNode;
+ /* Set the MDMA handle First linked List node*/
+ hmdma->FirstLinkedListNodeAddress = pNewNode;
+
+ /*reset New node link */
+ pNewNode->CLAR = 0;
+
+ /* Update the Handle last node address */
+ hmdma->LastLinkedListNodeAddress = pNewNode;
+
+ hmdma->LinkedListNodeCounter = 1;
+ }
+ else
+ {
+ hal_status = HAL_ERROR;
+ }
+ }
+ else if(hmdma->FirstLinkedListNodeAddress != pNewNode)
+ {
+ /* Check if the node to insert already exists*/
+ pNode = hmdma->FirstLinkedListNodeAddress;
+ while((counter < hmdma->LinkedListNodeCounter) && (hal_status == HAL_OK))
+ {
+ if(pNode->CLAR == (uint32_t)pNewNode)
+ {
+ hal_status = HAL_ERROR; /* error this node already exist in the linked list and it is not first node */
+ }
+ pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
+ counter++;
+ }
+
+ if(hal_status == HAL_OK)
+ {
+ /* Check if the previous node is the last one in the current list or zero */
+ if((pPrevNode == hmdma->LastLinkedListNodeAddress) || (pPrevNode == NULL))
+ {
+ /* insert the new node at the end of the list */
+ pNewNode->CLAR = hmdma->LastLinkedListNodeAddress->CLAR;
+ hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)pNewNode;
+ /* Update the Handle last node address */
+ hmdma->LastLinkedListNodeAddress = pNewNode;
+ /* Increment the linked list node counter */
+ hmdma->LinkedListNodeCounter++;
+ }
+ else
+ {
+ /*insert the new node after the pPreviousNode node */
+ pNode = hmdma->FirstLinkedListNodeAddress;
+ counter = 0;
+ while((counter < hmdma->LinkedListNodeCounter) && (nodeInserted == 0U))
+ {
+ counter++;
+ if(pNode == pPrevNode)
+ {
+ /*Insert the new node after the previous one */
+ pNewNode->CLAR = pNode->CLAR;
+ pNode->CLAR = (uint32_t)pNewNode;
+ /* Increment the linked list node counter */
+ hmdma->LinkedListNodeCounter++;
+ nodeInserted = 1;
+ }
+ else
+ {
+ pNode = (MDMA_LinkNodeTypeDef *)pNode->CLAR;
+ }
+ }
+
+ if(nodeInserted == 0U)
+ {
+ hal_status = HAL_ERROR;
+ }
+ }
+ }
+ }
+ else
+ {
+ hal_status = HAL_ERROR;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ return hal_status;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Return error status */
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Disconnect/Remove a node from the transfer linked list.
+ * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param pNode : Pointer to a MDMA_LinkNodeTypeDef structure that contains Linked list node
+ * to be removed from the list.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_LinkedList_RemoveNode(MDMA_HandleTypeDef *hmdma, MDMA_LinkNodeTypeDef *pNode)
+{
+ MDMA_LinkNodeTypeDef *ptmpNode;
+ uint32_t counter = 0, nodeDeleted = 0;
+ HAL_StatusTypeDef hal_status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if((hmdma == NULL) || (pNode == NULL))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* If first and last node are null (no nodes in the list) : return error*/
+ if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
+ {
+ hal_status = HAL_ERROR;
+ }
+ else if(hmdma->FirstLinkedListNodeAddress == pNode) /* Deleting first node */
+ {
+ /* Delete 1st node */
+ if(hmdma->LastLinkedListNodeAddress == pNode)
+ {
+ /*if the last node is at the same time the first one (1 single node after the init node 0)
+ then update the last node too */
+
+ hmdma->FirstLinkedListNodeAddress = 0;
+ hmdma->LastLinkedListNodeAddress = 0;
+ hmdma->LinkedListNodeCounter = 0;
+
+ hmdma->Instance->CLAR = 0;
+ }
+ else
+ {
+ if((uint32_t)hmdma->FirstLinkedListNodeAddress == hmdma->LastLinkedListNodeAddress->CLAR)
+ {
+ /* if last node is looping to first (circular list) one update the last node connection */
+ hmdma->LastLinkedListNodeAddress->CLAR = pNode->CLAR;
+ }
+
+ /* if deleting the first node after the initialization
+ connect the next node to the node 0 by updating
+ the MDMA channel CLAR register to this node address */
+ hmdma->Instance->CLAR = pNode->CLAR;
+ hmdma->FirstLinkedListNodeAddress = (MDMA_LinkNodeTypeDef *)hmdma->Instance->CLAR;
+ /* Update the Handle node counter */
+ hmdma->LinkedListNodeCounter--;
+ }
+ }
+ else /* Deleting any other node */
+ {
+ /*Deleted node is not the first one : find it */
+ ptmpNode = hmdma->FirstLinkedListNodeAddress;
+ while((counter < hmdma->LinkedListNodeCounter) && (nodeDeleted == 0U))
+ {
+ counter++;
+ if(ptmpNode->CLAR == ((uint32_t)pNode))
+ {
+ /* if deleting the last node */
+ if(pNode == hmdma->LastLinkedListNodeAddress)
+ {
+ /*Update the linked list last node address in the handle*/
+ hmdma->LastLinkedListNodeAddress = ptmpNode;
+ }
+ /* update the next node link after deleting pMDMA_LinkedListNode */
+ ptmpNode->CLAR = pNode->CLAR;
+ nodeDeleted = 1;
+ /* Update the Handle node counter */
+ hmdma->LinkedListNodeCounter--;
+ }
+ else
+ {
+ ptmpNode = (MDMA_LinkNodeTypeDef *)ptmpNode->CLAR;
+ }
+ }
+
+ if(nodeDeleted == 0U)
+ {
+ /* last node reashed without finding the node to delete : return error */
+ hal_status = HAL_ERROR;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ return hal_status;
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Return error status */
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Make the linked list circular by connecting the last node to the first.
+ * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_LinkedList_EnableCircularMode(MDMA_HandleTypeDef *hmdma)
+{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* If first and last node are null (no nodes in the list) : return error*/
+ if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
+ {
+ hal_status = HAL_ERROR;
+ }
+ else
+ {
+ /* to enable circular mode Last Node should be connected to first node */
+ hmdma->LastLinkedListNodeAddress->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
+ }
+
+ }
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ return hal_status;
+}
+
+/**
+ * @brief Disable the linked list circular mode by setting the last node connection to null
+ * @param hmdma : Pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_LinkedList_DisableCircularMode(MDMA_HandleTypeDef *hmdma)
+{
+ HAL_StatusTypeDef hal_status = HAL_OK;
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* If first and last node are null (no nodes in the list) : return error*/
+ if(((uint32_t)hmdma->FirstLinkedListNodeAddress == 0U) || ((uint32_t)hmdma->LastLinkedListNodeAddress == 0U) || (hmdma->LinkedListNodeCounter == 0U))
+ {
+ hal_status = HAL_ERROR;
+ }
+ else
+ {
+ /* to disable circular mode Last Node should be connected to NULL */
+ hmdma->LastLinkedListNodeAddress->CLAR = 0;
+ }
+
+ }
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ return hal_status;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup MDMA_Exported_Functions_Group3
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Configure the source, destination address and data length and Start MDMA transfer
+ (+) Configure the source, destination address and data length and
+ Start MDMA transfer with interrupt
+ (+) Abort MDMA transfer
+ (+) Poll for transfer complete
+ (+) Generate a SW request (when Request is set to MDMA_REQUEST_SW)
+ (+) Handle MDMA interrupt request
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the MDMA Transfer.
+ * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param SrcAddress : The source memory Buffer address
+ * @param DstAddress : The destination memory Buffer address
+ * @param BlockDataLength : The length of a block transfer in bytes
+ * @param BlockCount : The number of a blocks to be transfer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_Start(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
+{
+ /* Check the parameters */
+ assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
+ assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* Initialize the error code */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
+
+ /* Disable the peripheral */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Configure the source, destination address and the data length */
+ MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
+
+ /* Enable the Peripheral */
+ __HAL_MDMA_ENABLE(hmdma);
+
+ if(hmdma->Init.Request == MDMA_REQUEST_SW)
+ {
+ /* activate If SW request mode*/
+ hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Return error status */
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the MDMA Transfer with interrupts enabled.
+ * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param SrcAddress : The source memory Buffer address
+ * @param DstAddress : The destination memory Buffer address
+ * @param BlockDataLength : The length of a block transfer in bytes
+ * @param BlockCount : The number of a blocks to be transfer
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
+{
+ /* Check the parameters */
+ assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
+ assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hmdma);
+
+ if(HAL_MDMA_STATE_READY == hmdma->State)
+ {
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_BUSY;
+
+ /* Initialize the error code */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
+
+ /* Disable the peripheral */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Configure the source, destination address and the data length */
+ MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
+
+ /* Enable Common interrupts i.e Transfer Error IT and Channel Transfer Complete IT*/
+ __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
+
+ if(hmdma->XferBlockCpltCallback != NULL)
+ {
+ /* if Block transfer complete Callback is set enable the corresponding IT*/
+ __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);
+ }
+
+ if(hmdma->XferRepeatBlockCpltCallback != NULL)
+ {
+ /* if Repeated Block transfer complete Callback is set enable the corresponding IT*/
+ __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);
+ }
+
+ if(hmdma->XferBufferCpltCallback != NULL)
+ {
+ /* if buffer transfer complete Callback is set enable the corresponding IT*/
+ __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);
+ }
+
+ /* Enable the Peripheral */
+ __HAL_MDMA_ENABLE(hmdma);
+
+ if(hmdma->Init.Request == MDMA_REQUEST_SW)
+ {
+ /* activate If SW request mode*/
+ hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Return error status */
+ return HAL_BUSY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Aborts the MDMA Transfer.
+ * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ *
+ * @note After disabling a MDMA Channel, a check for wait until the MDMA Channel is
+ * effectively disabled is added. If a Channel is disabled
+ * while a data transfer is ongoing, the current data will be transferred
+ * and the Channel will be effectively disabled only after the transfer of
+ * this single data is finished.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_Abort(MDMA_HandleTypeDef *hmdma)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(HAL_MDMA_STATE_BUSY != hmdma->State)
+ {
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Disable all the transfer interrupts */
+ __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
+
+ /* Disable the channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Check if the MDMA Channel is effectively disabled */
+ while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
+ {
+ /* Check for the Timeout */
+ if( (HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)
+ {
+ /* Update error code */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Change the MDMA state */
+ hmdma->State = HAL_MDMA_STATE_ERROR;
+
+ return HAL_ERROR;
+ }
+ }
+
+ /* Clear all interrupt flags */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_FLAG_BT | MDMA_FLAG_BRT | MDMA_FLAG_BFTC));
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Change the MDMA state*/
+ hmdma->State = HAL_MDMA_STATE_READY;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Aborts the MDMA Transfer in Interrupt mode.
+ * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_Abort_IT(MDMA_HandleTypeDef *hmdma)
+{
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(HAL_MDMA_STATE_BUSY != hmdma->State)
+ {
+ /* No transfer ongoing */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Set Abort State */
+ hmdma->State = HAL_MDMA_STATE_ABORT;
+
+ /* Disable the stream */
+ __HAL_MDMA_DISABLE(hmdma);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Polling for transfer complete.
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param CompleteLevel: Specifies the MDMA level complete.
+ * @param Timeout: Timeout duration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_PollForTransfer(MDMA_HandleTypeDef *hmdma, HAL_MDMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
+{
+ uint32_t levelFlag, errorFlag;
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_MDMA_LEVEL_COMPLETE(CompleteLevel));
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if(HAL_MDMA_STATE_BUSY != hmdma->State)
+ {
+ /* No transfer ongoing */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
+
+ return HAL_ERROR;
+ }
+
+ /* Get the level transfer complete flag */
+ levelFlag = ((CompleteLevel == HAL_MDMA_FULL_TRANSFER) ? MDMA_FLAG_CTC : \
+ (CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)? MDMA_FLAG_BFTC : \
+ (CompleteLevel == HAL_MDMA_BLOCK_TRANSFER) ? MDMA_FLAG_BT : \
+ MDMA_FLAG_BRT);
+
+
+ /* Get timeout */
+ tickstart = HAL_GetTick();
+
+ while(__HAL_MDMA_GET_FLAG(hmdma, levelFlag) == 0U)
+ {
+ if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
+ {
+ /* Get the transfer error source flag */
+ errorFlag = hmdma->Instance->CESR;
+
+ if((errorFlag & MDMA_CESR_TED) == 0U)
+ {
+ /* Update error code : Read Transfer error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
+ }
+ else
+ {
+ /* Update error code : Write Transfer error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
+ }
+
+ if((errorFlag & MDMA_CESR_TEMD) != 0U)
+ {
+ /* Update error code : Error Mask Data */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
+ }
+
+ if((errorFlag & MDMA_CESR_TELD) != 0U)
+ {
+ /* Update error code : Error Linked list */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
+ }
+
+ if((errorFlag & MDMA_CESR_ASE) != 0U)
+ {
+ /* Update error code : Address/Size alignment error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
+ }
+
+ if((errorFlag & MDMA_CESR_BSE) != 0U)
+ {
+ /* Update error code : Block Size error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
+ }
+
+ (void) HAL_MDMA_Abort(hmdma); /* if error then abort the current transfer */
+
+ /*
+ Note that the Abort function will
+ - Clear all transfer flags
+ - Unlock
+ - Set the State
+ */
+
+ return HAL_ERROR;
+
+ }
+
+ /* Check for the Timeout */
+ if(Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - tickstart ) > Timeout) || (Timeout == 0U))
+ {
+ /* Update error code */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_TIMEOUT;
+
+ (void) HAL_MDMA_Abort(hmdma); /* if timeout then abort the current transfer */
+
+ /*
+ Note that the Abort function will
+ - Clear all transfer flags
+ - Unlock
+ - Set the State
+ */
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ /* Clear the transfer level flag */
+ if(CompleteLevel == HAL_MDMA_BUFFER_TRANSFER)
+ {
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
+
+ }
+ else if(CompleteLevel == HAL_MDMA_BLOCK_TRANSFER)
+ {
+ __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT));
+
+ }
+ else if(CompleteLevel == HAL_MDMA_REPEAT_BLOCK_TRANSFER)
+ {
+ __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BFTC | MDMA_FLAG_BT | MDMA_FLAG_BRT));
+ }
+ else if(CompleteLevel == HAL_MDMA_FULL_TRANSFER)
+ {
+ __HAL_MDMA_CLEAR_FLAG(hmdma, (MDMA_FLAG_BRT | MDMA_FLAG_BT | MDMA_FLAG_BFTC | MDMA_FLAG_CTC));
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ hmdma->State = HAL_MDMA_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Generate an MDMA SW request trigger to activate the request on the given Channel.
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Stream.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_MDMA_GenerateSWRequest(MDMA_HandleTypeDef *hmdma)
+{
+ uint32_t request_mode;
+
+ /* Check the MDMA peripheral handle */
+ if(hmdma == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get the softawre request mode */
+ request_mode = hmdma->Instance->CTCR & MDMA_CTCR_SWRM;
+
+ if((hmdma->Instance->CCR & MDMA_CCR_EN) == 0U)
+ {
+ /* if no Transfer on going (MDMA enable bit not set) return error */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_NO_XFER;
+
+ return HAL_ERROR;
+ }
+ else if(((hmdma->Instance->CISR & MDMA_CISR_CRQA) != 0U) || (request_mode == 0U))
+ {
+ /* if an MDMA ongoing request has not yet end or if request mode is not SW request return error */
+ hmdma->ErrorCode = HAL_MDMA_ERROR_BUSY;
+
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Set the SW request bit to activate the request on the Channel */
+ hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
+
+ return HAL_OK;
+ }
+}
+
+/**
+ * @brief Handles MDMA interrupt request.
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval None
+ */
+void HAL_MDMA_IRQHandler(MDMA_HandleTypeDef *hmdma)
+{
+ __IO uint32_t count = 0;
+ uint32_t timeout = SystemCoreClock / 9600U;
+
+ uint32_t generalIntFlag, errorFlag;
+
+ /* General Interrupt Flag management ****************************************/
+ generalIntFlag = 1UL << ((((uint32_t)hmdma->Instance - (uint32_t)(MDMA_Channel0))/HAL_MDMA_CHANNEL_SIZE) & 0x1FU);
+ if((MDMA->GISR0 & generalIntFlag) == 0U)
+ {
+ return; /* the General interrupt flag for the current channel is down , nothing to do */
+ }
+
+ /* Transfer Error Interrupt management ***************************************/
+ if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_TE) != 0U))
+ {
+ if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_TE) != 0U)
+ {
+ /* Disable the transfer error interrupt */
+ __HAL_MDMA_DISABLE_IT(hmdma, MDMA_IT_TE);
+
+ /* Get the transfer error source flag */
+ errorFlag = hmdma->Instance->CESR;
+
+ if((errorFlag & MDMA_CESR_TED) == 0U)
+ {
+ /* Update error code : Read Transfer error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_READ_XFER;
+ }
+ else
+ {
+ /* Update error code : Write Transfer error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_WRITE_XFER;
+ }
+
+ if((errorFlag & MDMA_CESR_TEMD) != 0U)
+ {
+ /* Update error code : Error Mask Data */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_MASK_DATA;
+ }
+
+ if((errorFlag & MDMA_CESR_TELD) != 0U)
+ {
+ /* Update error code : Error Linked list */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_LINKED_LIST;
+ }
+
+ if((errorFlag & MDMA_CESR_ASE) != 0U)
+ {
+ /* Update error code : Address/Size alignment error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_ALIGNMENT;
+ }
+
+ if((errorFlag & MDMA_CESR_BSE) != 0U)
+ {
+ /* Update error code : Block Size error error */
+ hmdma->ErrorCode |= HAL_MDMA_ERROR_BLOCK_SIZE;
+ }
+
+ /* Clear the transfer error flags */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE);
+ }
+ }
+
+ /* Buffer Transfer Complete Interrupt management ******************************/
+ if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BFTC) != 0U))
+ {
+ if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BFTC) != 0U)
+ {
+ /* Clear the buffer transfer complete flag */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BFTC);
+
+ if(hmdma->XferBufferCpltCallback != NULL)
+ {
+ /* Buffer transfer callback */
+ hmdma->XferBufferCpltCallback(hmdma);
+ }
+ }
+ }
+
+ /* Block Transfer Complete Interrupt management ******************************/
+ if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BT) != 0U))
+ {
+ if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BT) != 0U)
+ {
+ /* Clear the block transfer complete flag */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BT);
+
+ if(hmdma->XferBlockCpltCallback != NULL)
+ {
+ /* Block transfer callback */
+ hmdma->XferBlockCpltCallback(hmdma);
+ }
+ }
+ }
+
+ /* Repeated Block Transfer Complete Interrupt management ******************************/
+ if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_BRT) != 0U))
+ {
+ if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_BRT) != 0U)
+ {
+ /* Clear the repeat block transfer complete flag */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_BRT);
+
+ if(hmdma->XferRepeatBlockCpltCallback != NULL)
+ {
+ /* Repeated Block transfer callback */
+ hmdma->XferRepeatBlockCpltCallback(hmdma);
+ }
+ }
+ }
+
+ /* Channel Transfer Complete Interrupt management ***********************************/
+ if((__HAL_MDMA_GET_FLAG(hmdma, MDMA_FLAG_CTC) != 0U))
+ {
+ if(__HAL_MDMA_GET_IT_SOURCE(hmdma, MDMA_IT_CTC) != 0U)
+ {
+ /* Disable all the transfer interrupts */
+ __HAL_MDMA_DISABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC | MDMA_IT_BT | MDMA_IT_BRT | MDMA_IT_BFTC));
+
+ if(HAL_MDMA_STATE_ABORT == hmdma->State)
+ {
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Change the DMA state */
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ if(hmdma->XferAbortCallback != NULL)
+ {
+ hmdma->XferAbortCallback(hmdma);
+ }
+ return;
+ }
+
+ /* Clear the Channel Transfer Complete flag */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_CTC);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ /* Change MDMA peripheral state */
+ hmdma->State = HAL_MDMA_STATE_READY;
+
+ if(hmdma->XferCpltCallback != NULL)
+ {
+ /* Channel Transfer Complete callback */
+ hmdma->XferCpltCallback(hmdma);
+ }
+ }
+ }
+
+ /* manage error case */
+ if(hmdma->ErrorCode != HAL_MDMA_ERROR_NONE)
+ {
+ hmdma->State = HAL_MDMA_STATE_ABORT;
+
+ /* Disable the channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ do
+ {
+ if (++count > timeout)
+ {
+ break;
+ }
+ }
+ while((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hmdma);
+
+ if((hmdma->Instance->CCR & MDMA_CCR_EN) != 0U)
+ {
+ /* Change the MDMA state to error if MDMA disable fails */
+ hmdma->State = HAL_MDMA_STATE_ERROR;
+ }
+ else
+ {
+ /* Change the MDMA state to Ready if MDMA disable success */
+ hmdma->State = HAL_MDMA_STATE_READY;
+ }
+
+
+ if (hmdma->XferErrorCallback != NULL)
+ {
+ /* Transfer error callback */
+ hmdma->XferErrorCallback(hmdma);
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup MDMA_Exported_Functions_Group4
+ *
+@verbatim
+ ===============================================================================
+ ##### State and Errors functions #####
+ ===============================================================================
+ [..]
+ This subsection provides functions allowing to
+ (+) Check the MDMA state
+ (+) Get error code
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the MDMA state.
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval HAL state
+ */
+HAL_MDMA_StateTypeDef HAL_MDMA_GetState(const MDMA_HandleTypeDef *hmdma)
+{
+ return hmdma->State;
+}
+
+/**
+ * @brief Return the MDMA error code
+ * @param hmdma : pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval MDMA Error Code
+ */
+uint32_t HAL_MDMA_GetError(const MDMA_HandleTypeDef *hmdma)
+{
+ return hmdma->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup MDMA_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Sets the MDMA Transfer parameter.
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @param SrcAddress: The source memory Buffer address
+ * @param DstAddress: The destination memory Buffer address
+ * @param BlockDataLength : The length of a block transfer in bytes
+ * @param BlockCount: The number of blocks to be transferred
+ * @retval HAL status
+ */
+static void MDMA_SetConfig(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
+{
+ uint32_t addressMask;
+
+ /* Configure the MDMA Channel data length */
+ MODIFY_REG(hmdma->Instance->CBNDTR ,MDMA_CBNDTR_BNDT, (BlockDataLength & MDMA_CBNDTR_BNDT));
+
+ /* Configure the MDMA block repeat count */
+ MODIFY_REG(hmdma->Instance->CBNDTR , MDMA_CBNDTR_BRC , ((BlockCount - 1U) << MDMA_CBNDTR_BRC_Pos) & MDMA_CBNDTR_BRC);
+
+ /* Clear all interrupt flags */
+ __HAL_MDMA_CLEAR_FLAG(hmdma, MDMA_FLAG_TE | MDMA_FLAG_CTC | MDMA_CISR_BRTIF | MDMA_CISR_BTIF | MDMA_CISR_TCIF);
+
+ /* Configure MDMA Channel destination address */
+ hmdma->Instance->CDAR = DstAddress;
+
+ /* Configure MDMA Channel Source address */
+ hmdma->Instance->CSAR = SrcAddress;
+
+ addressMask = SrcAddress & 0xFF000000U;
+ if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
+ {
+ /*The AHBSbus is used as source (read operation) on channel x */
+ hmdma->Instance->CTBR |= MDMA_CTBR_SBUS;
+ }
+ else
+ {
+ /*The AXI bus is used as source (read operation) on channel x */
+ hmdma->Instance->CTBR &= (~MDMA_CTBR_SBUS);
+ }
+
+ addressMask = DstAddress & 0xFF000000U;
+ if((addressMask == 0x20000000U) || (addressMask == 0x00000000U))
+ {
+ /*The AHB bus is used as destination (write operation) on channel x */
+ hmdma->Instance->CTBR |= MDMA_CTBR_DBUS;
+ }
+ else
+ {
+ /*The AXI bus is used as destination (write operation) on channel x */
+ hmdma->Instance->CTBR &= (~MDMA_CTBR_DBUS);
+ }
+
+ /* Set the linked list register to the first node of the list */
+ hmdma->Instance->CLAR = (uint32_t)hmdma->FirstLinkedListNodeAddress;
+}
+
+/**
+ * @brief Initializes the MDMA handle according to the specified
+ * parameters in the MDMA_InitTypeDef
+ * @param hmdma: pointer to a MDMA_HandleTypeDef structure that contains
+ * the configuration information for the specified MDMA Channel.
+ * @retval None
+ */
+static void MDMA_Init(MDMA_HandleTypeDef *hmdma)
+{
+ uint32_t blockoffset;
+
+ /* Prepare the MDMA Channel configuration */
+ hmdma->Instance->CCR = hmdma->Init.Priority | hmdma->Init.Endianness;
+
+ /* Write new CTCR Register value */
+ hmdma->Instance->CTCR = hmdma->Init.SourceInc | hmdma->Init.DestinationInc | \
+ hmdma->Init.SourceDataSize | hmdma->Init.DestDataSize | \
+ hmdma->Init.DataAlignment | hmdma->Init.SourceBurst | \
+ hmdma->Init.DestBurst | \
+ ((hmdma->Init.BufferTransferLength - 1U) << MDMA_CTCR_TLEN_Pos) | \
+ hmdma->Init.TransferTriggerMode;
+
+ /* If SW request set the CTCR register to SW Request Mode */
+ if(hmdma->Init.Request == MDMA_REQUEST_SW)
+ {
+ /*
+ -If the request is done by SW : BWM could be set to 1 or 0.
+ -If the request is done by a peripheral :
+ If mask address not set (0) => BWM must be set to 0
+ If mask address set (different than 0) => BWM could be set to 1 or 0
+ */
+ hmdma->Instance->CTCR |= (MDMA_CTCR_SWRM | MDMA_CTCR_BWM);
+ }
+
+ /* Reset CBNDTR Register */
+ hmdma->Instance->CBNDTR = 0;
+
+ /* if block source address offset is negative set the Block Repeat Source address Update Mode to decrement */
+ if(hmdma->Init.SourceBlockAddressOffset < 0)
+ {
+ hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRSUM;
+ /* Write new CBRUR Register value : source repeat block offset */
+ blockoffset = (uint32_t)(- hmdma->Init.SourceBlockAddressOffset);
+ hmdma->Instance->CBRUR = (blockoffset & 0x0000FFFFU);
+ }
+ else
+ {
+ /* Write new CBRUR Register value : source repeat block offset */
+ hmdma->Instance->CBRUR = (((uint32_t)hmdma->Init.SourceBlockAddressOffset) & 0x0000FFFFU);
+ }
+
+ /* If block destination address offset is negative set the Block Repeat destination address Update Mode to decrement */
+ if(hmdma->Init.DestBlockAddressOffset < 0)
+ {
+ hmdma->Instance->CBNDTR |= MDMA_CBNDTR_BRDUM;
+ /* Write new CBRUR Register value : destination repeat block offset */
+ blockoffset = (uint32_t)(- hmdma->Init.DestBlockAddressOffset);
+ hmdma->Instance->CBRUR |= ((blockoffset & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
+ }
+ else
+ {
+ /*write new CBRUR Register value : destination repeat block offset */
+ hmdma->Instance->CBRUR |= ((((uint32_t)hmdma->Init.DestBlockAddressOffset) & 0x0000FFFFU) << MDMA_CBRUR_DUV_Pos);
+ }
+
+ /* if HW request set the HW request and the requet CleraMask and ClearData MaskData, */
+ if(hmdma->Init.Request != MDMA_REQUEST_SW)
+ {
+ /* Set the HW request in CTRB register */
+ hmdma->Instance->CTBR = hmdma->Init.Request & MDMA_CTBR_TSEL;
+ }
+ else /* SW request : reset the CTBR register */
+ {
+ hmdma->Instance->CTBR = 0;
+ }
+
+ /* Write Link Address Register */
+ hmdma->Instance->CLAR = 0;
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_MDMA_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nand.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nand.c
new file mode 100755
index 0000000..162b761
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nand.c
@@ -0,0 +1,2199 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_nand.c
+ * @author MCD Application Team
+ * @brief NAND HAL module driver.
+ * This file provides a generic firmware to drive NAND memories mounted
+ * as external device.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a generic layered driver which contains a set of APIs used to
+ control NAND flash memories. It uses the FMC layer functions to interface
+ with NAND devices. This driver is used as follows:
+
+ (+) NAND flash memory configuration sequence using the function HAL_NAND_Init()
+ with control and timing parameters for both common and attribute spaces.
+
+ (+) Read NAND flash memory maker and device IDs using the function
+ HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef
+ structure declared by the function caller.
+
+ (+) Access NAND flash memory by read/write operations using the functions
+ HAL_NAND_Read_Page_8b()/HAL_NAND_Read_SpareArea_8b(),
+ HAL_NAND_Write_Page_8b()/HAL_NAND_Write_SpareArea_8b(),
+ HAL_NAND_Read_Page_16b()/HAL_NAND_Read_SpareArea_16b(),
+ HAL_NAND_Write_Page_16b()/HAL_NAND_Write_SpareArea_16b()
+ to read/write page(s)/spare area(s). These functions use specific device
+ information (Block, page size..) predefined by the user in the NAND_DeviceConfigTypeDef
+ structure. The read/write address information is contained by the Nand_Address_Typedef
+ structure passed as parameter.
+
+ (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset().
+
+ (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block().
+ The erase block address information is contained in the Nand_Address_Typedef
+ structure passed as parameter.
+
+ (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status().
+
+ (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/
+ HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction
+ feature or the function HAL_NAND_GetECC() to get the ECC correction code.
+
+ (+) You can monitor the NAND device HAL state by calling the function
+ HAL_NAND_GetState()
+
+ [..]
+ (@) This driver is a set of generic APIs which handle standard NAND flash operations.
+ If a NAND flash device contains different operations and/or implementations,
+ it should be implemented separately.
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_NAND_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions HAL_NAND_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) MspInitCallback : NAND MspInit.
+ (+) MspDeInitCallback : NAND MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function HAL_NAND_UnRegisterCallback() to reset a callback to the default
+ weak (overridden) function. It allows to reset following callbacks:
+ (+) MspInitCallback : NAND MspInit.
+ (+) MspDeInitCallback : NAND MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the HAL_NAND_Init and if the state is HAL_NAND_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (overridden) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (overridden) functions in the HAL_NAND_Init
+ and HAL_NAND_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_NAND_Init and HAL_NAND_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in READY state only.
+ Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
+ in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
+ during the Init/DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_NAND_RegisterCallback before calling HAL_NAND_DeInit
+ or HAL_NAND_Init function.
+
+ When The compilation define USE_HAL_NAND_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (overridden) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_NAND_MODULE_ENABLED
+
+/** @defgroup NAND NAND
+ * @brief NAND HAL module driver
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private Constants ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions ---------------------------------------------------------*/
+
+/** @defgroup NAND_Exported_Functions NAND Exported Functions
+ * @{
+ */
+
+/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### NAND Initialization and de-initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to initialize/de-initialize
+ the NAND memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Perform NAND memory Initialization sequence
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param ComSpace_Timing pointer to Common space timing structure
+ * @param AttSpace_Timing pointer to Attribute space timing structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing,
+ FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing)
+{
+ /* Check the NAND handle state */
+ if (hnand == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hnand->State == HAL_NAND_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hnand->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+ if (hnand->MspInitCallback == NULL)
+ {
+ hnand->MspInitCallback = HAL_NAND_MspInit;
+ }
+ hnand->ItCallback = HAL_NAND_ITCallback;
+
+ /* Init the low level hardware */
+ hnand->MspInitCallback(hnand);
+#else
+ /* Initialize the low level hardware (MSP) */
+ HAL_NAND_MspInit(hnand);
+#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
+ }
+
+ /* Initialize NAND control Interface */
+ (void)FMC_NAND_Init(hnand->Instance, &(hnand->Init));
+
+ /* Initialize NAND common space timing Interface */
+ (void)FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank);
+
+ /* Initialize NAND attribute space timing Interface */
+ (void)FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank);
+
+ /* Enable the NAND device */
+ __FMC_NAND_ENABLE(hnand->Instance);
+
+ /* Enable FMC Peripheral */
+ __FMC_ENABLE();
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Perform NAND memory De-Initialization sequence
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand)
+{
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+ if (hnand->MspDeInitCallback == NULL)
+ {
+ hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hnand->MspDeInitCallback(hnand);
+#else
+ /* Initialize the low level hardware (MSP) */
+ HAL_NAND_MspDeInit(hnand);
+#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
+
+ /* Configure the NAND registers with their reset values */
+ (void)FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank);
+
+ /* Reset the NAND controller state */
+ hnand->State = HAL_NAND_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief NAND MSP Init
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval None
+ */
+__weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hnand);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_NAND_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief NAND MSP DeInit
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval None
+ */
+__weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hnand);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_NAND_MspDeInit could be implemented in the user file
+ */
+}
+
+
+/**
+ * @brief This function handles NAND device interrupt request.
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval HAL status
+ */
+void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)
+{
+ /* Check NAND interrupt Rising edge flag */
+ if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE))
+ {
+ /* NAND interrupt callback*/
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+ hnand->ItCallback(hnand);
+#else
+ HAL_NAND_ITCallback(hnand);
+#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
+
+ /* Clear NAND interrupt Rising edge pending bit */
+ __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_RISING_EDGE);
+ }
+
+ /* Check NAND interrupt Level flag */
+ if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL))
+ {
+ /* NAND interrupt callback*/
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+ hnand->ItCallback(hnand);
+#else
+ HAL_NAND_ITCallback(hnand);
+#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
+
+ /* Clear NAND interrupt Level pending bit */
+ __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_LEVEL);
+ }
+
+ /* Check NAND interrupt Falling edge flag */
+ if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE))
+ {
+ /* NAND interrupt callback*/
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+ hnand->ItCallback(hnand);
+#else
+ HAL_NAND_ITCallback(hnand);
+#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
+
+ /* Clear NAND interrupt Falling edge pending bit */
+ __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_FALLING_EDGE);
+ }
+
+ /* Check NAND interrupt FIFO empty flag */
+ if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT))
+ {
+ /* NAND interrupt callback*/
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+ hnand->ItCallback(hnand);
+#else
+ HAL_NAND_ITCallback(hnand);
+#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
+
+ /* Clear NAND interrupt FIFO empty pending bit */
+ __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_FEMPT);
+ }
+
+}
+
+/**
+ * @brief NAND interrupt feature callback
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval None
+ */
+__weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hnand);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_NAND_ITCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions
+ * @brief Input Output and memory control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### NAND Input and Output functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to use and control the NAND
+ memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Read the NAND memory electronic signature
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pNAND_ID NAND ID structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
+{
+ __IO uint32_t data = 0;
+ __IO uint32_t data1 = 0;
+ uint32_t deviceaddress;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* Send Read ID command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
+ __DSB();
+
+ /* Read the electronic signature from NAND flash */
+ if (hnand->Init.MemoryDataWidth == FMC_NAND_MEM_BUS_WIDTH_8)
+ {
+ data = *(__IO uint32_t *)deviceaddress;
+
+ /* Return the data read */
+ pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data);
+ pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data);
+ pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data);
+ pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data);
+ }
+ else
+ {
+ data = *(__IO uint32_t *)deviceaddress;
+ data1 = *((__IO uint32_t *)deviceaddress + 4);
+
+ /* Return the data read */
+ pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data);
+ pNAND_ID->Device_Id = ADDR_3RD_CYCLE(data);
+ pNAND_ID->Third_Id = ADDR_1ST_CYCLE(data1);
+ pNAND_ID->Fourth_Id = ADDR_3RD_CYCLE(data1);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief NAND memory reset
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
+{
+ uint32_t deviceaddress;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* Send NAND reset command */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+
+}
+
+/**
+ * @brief Configure the device: Enter the physical parameters of the device
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pDeviceConfig pointer to NAND_DeviceConfigTypeDef structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, const NAND_DeviceConfigTypeDef *pDeviceConfig)
+{
+ hnand->Config.PageSize = pDeviceConfig->PageSize;
+ hnand->Config.SpareAreaSize = pDeviceConfig->SpareAreaSize;
+ hnand->Config.BlockSize = pDeviceConfig->BlockSize;
+ hnand->Config.BlockNbr = pDeviceConfig->BlockNbr;
+ hnand->Config.PlaneSize = pDeviceConfig->PlaneSize;
+ hnand->Config.PlaneNbr = pDeviceConfig->PlaneNbr;
+ hnand->Config.ExtraCommandEnable = pDeviceConfig->ExtraCommandEnable;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read Page(s) from NAND memory block (8-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to destination read buffer
+ * @param NumPageToRead number of pages to read from block
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ uint8_t *pBuffer, uint32_t NumPageToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t nbpages = NumPageToRead;
+ uint8_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Page(s) read loop */
+ while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Send read page command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
+ __DSB();
+
+
+ if (hnand->Config.ExtraCommandEnable == ENABLE)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Go back to read mode */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.PageSize; index++)
+ {
+ *buff = *(__IO uint8_t *)deviceaddress;
+ buff++;
+ }
+
+ /* Decrement pages to read */
+ nbpages--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read Page(s) from NAND memory block (16-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to destination read buffer. pBuffer should be 16bits aligned
+ * @param NumPageToRead number of pages to read from block
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ uint16_t *pBuffer, uint32_t NumPageToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t nbpages = NumPageToRead;
+ uint16_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Page(s) read loop */
+ while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Send read page command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
+ __DSB();
+
+ if (hnand->Config.ExtraCommandEnable == ENABLE)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Go back to read mode */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
+ __DSB();
+ }
+
+ /* Calculate PageSize */
+ if (hnand->Init.MemoryDataWidth == FMC_NAND_MEM_BUS_WIDTH_8)
+ {
+ hnand->Config.PageSize = hnand->Config.PageSize / 2U;
+ }
+ else
+ {
+ /* Do nothing */
+ /* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.PageSize; index++)
+ {
+ *buff = *(__IO uint16_t *)deviceaddress;
+ buff++;
+ }
+
+ /* Decrement pages to read */
+ nbpages--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Write Page(s) to NAND memory block (8-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to source buffer to write
+ * @param NumPageToWrite number of pages to write to block
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ const uint8_t *pBuffer, uint32_t NumPageToWrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t nbpages = NumPageToWrite;
+ const uint8_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Page(s) write loop */
+ while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Send write page command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
+ __DSB();
+
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ /* Write data to memory */
+ for (index = 0U; index < hnand->Config.PageSize; index++)
+ {
+ *(__IO uint8_t *)deviceaddress = *buff;
+ buff++;
+ __DSB();
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+ __DSB();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Decrement pages to write */
+ nbpages--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Write Page(s) to NAND memory block (16-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned
+ * @param NumPageToWrite number of pages to write to block
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ const uint16_t *pBuffer, uint32_t NumPageToWrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t nbpages = NumPageToWrite;
+ const uint16_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Page(s) write loop */
+ while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Send write page command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
+ __DSB();
+
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ /* Calculate PageSize */
+ if (hnand->Init.MemoryDataWidth == FMC_NAND_MEM_BUS_WIDTH_8)
+ {
+ hnand->Config.PageSize = hnand->Config.PageSize / 2U;
+ }
+ else
+ {
+ /* Do nothing */
+ /* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/
+ }
+
+ /* Write data to memory */
+ for (index = 0U; index < hnand->Config.PageSize; index++)
+ {
+ *(__IO uint16_t *)deviceaddress = *buff;
+ buff++;
+ __DSB();
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+ __DSB();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Decrement pages to write */
+ nbpages--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read Spare area(s) from NAND memory (8-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to source buffer to write
+ * @param NumSpareAreaToRead Number of spare area to read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t columnaddress;
+ uint32_t nbspare = NumSpareAreaToRead;
+ uint8_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Column in page address */
+ columnaddress = COLUMN_ADDRESS(hnand);
+
+ /* Spare area(s) read loop */
+ while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ /* Send read spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ /* Send read spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
+ __DSB();
+
+ if (hnand->Config.ExtraCommandEnable == ENABLE)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Go back to read mode */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
+ {
+ *buff = *(__IO uint8_t *)deviceaddress;
+ buff++;
+ }
+
+ /* Decrement spare areas to read */
+ nbspare--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read Spare area(s) from NAND memory (16-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned.
+ * @param NumSpareAreaToRead Number of spare area to read
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ uint16_t *pBuffer, uint32_t NumSpareAreaToRead)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t columnaddress;
+ uint32_t nbspare = NumSpareAreaToRead;
+ uint16_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Column in page address */
+ columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand));
+
+ /* Spare area(s) read loop */
+ while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ /* Send read spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ /* Send read spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
+ __DSB();
+
+ if (hnand->Config.ExtraCommandEnable == ENABLE)
+ {
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Go back to read mode */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
+ __DSB();
+ }
+
+ /* Get Data into Buffer */
+ for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
+ {
+ *buff = *(__IO uint16_t *)deviceaddress;
+ buff++;
+ }
+
+ /* Decrement spare areas to read */
+ nbspare--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Write Spare area(s) to NAND memory (8-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to source buffer to write
+ * @param NumSpareAreaTowrite number of spare areas to write to block
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ const uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t columnaddress;
+ uint32_t nbspare = NumSpareAreaTowrite;
+ const uint8_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* Page address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Column in page address */
+ columnaddress = COLUMN_ADDRESS(hnand);
+
+ /* Spare area(s) write loop */
+ while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ /* Send write Spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ /* Send write Spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ /* Write data to memory */
+ for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
+ {
+ *(__IO uint8_t *)deviceaddress = *buff;
+ buff++;
+ __DSB();
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+ __DSB();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Decrement spare areas to write */
+ nbspare--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Write Spare area(s) to NAND memory (16-bits addressing)
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned.
+ * @param NumSpareAreaTowrite number of spare areas to write to block
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
+ const uint16_t *pBuffer, uint32_t NumSpareAreaTowrite)
+{
+ uint32_t index;
+ uint32_t tickstart;
+ uint32_t deviceaddress;
+ uint32_t nandaddress;
+ uint32_t columnaddress;
+ uint32_t nbspare = NumSpareAreaTowrite;
+ const uint16_t *buff = pBuffer;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* NAND raw address calculation */
+ nandaddress = ARRAY_ADDRESS(pAddress, hnand);
+
+ /* Column in page address */
+ columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand));
+
+ /* Spare area(s) write loop */
+ while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
+ {
+ /* Cards with page size <= 512 bytes */
+ if ((hnand->Config.PageSize) <= 512U)
+ {
+ /* Send write Spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+ else /* (hnand->Config.PageSize) > 512 */
+ {
+ /* Send write Spare area command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
+ __DSB();
+
+ if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ }
+ else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
+ {
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
+ __DSB();
+ }
+ }
+
+ /* Write data to memory */
+ for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
+ {
+ *(__IO uint16_t *)deviceaddress = *buff;
+ buff++;
+ __DSB();
+ }
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
+ __DSB();
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Read status until NAND is ready */
+ while (HAL_NAND_Read_Status(hnand) != NAND_READY)
+ {
+ if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
+ {
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Decrement spare areas to write */
+ nbspare--;
+
+ /* Increment the NAND address */
+ nandaddress = (uint32_t)(nandaddress + 1U);
+ }
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief NAND memory Block erase
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress)
+{
+ uint32_t deviceaddress;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnand);
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* Send Erase block command sequence */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
+ __DSB();
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
+ __DSB();
+
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1;
+ __DSB();
+
+ /* Update the NAND controller state */
+ hnand->State = HAL_NAND_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnand);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Increment the NAND memory address
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param pAddress pointer to NAND address structure
+ * @retval The new status of the increment address operation. It can be:
+ * - NAND_VALID_ADDRESS: When the new address is valid address
+ * - NAND_INVALID_ADDRESS: When the new address is invalid address
+ */
+uint32_t HAL_NAND_Address_Inc(const NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
+{
+ uint32_t status = NAND_VALID_ADDRESS;
+
+ /* Increment page address */
+ pAddress->Page++;
+
+ /* Check NAND address is valid */
+ if (pAddress->Page == hnand->Config.BlockSize)
+ {
+ pAddress->Page = 0;
+ pAddress->Block++;
+
+ if (pAddress->Block == hnand->Config.PlaneSize)
+ {
+ pAddress->Block = 0;
+ pAddress->Plane++;
+
+ if (pAddress->Plane == (hnand->Config.PlaneNbr))
+ {
+ status = NAND_INVALID_ADDRESS;
+ }
+ }
+ }
+
+ return (status);
+}
+
+#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User NAND Callback
+ * To be used to override the weak predefined callback
+ * @param hnand : NAND handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID
+ * @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID
+ * @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_NAND_RegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId,
+ pNAND_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_NAND_MSP_INIT_CB_ID :
+ hnand->MspInitCallback = pCallback;
+ break;
+ case HAL_NAND_MSP_DEINIT_CB_ID :
+ hnand->MspDeInitCallback = pCallback;
+ break;
+ case HAL_NAND_IT_CB_ID :
+ hnand->ItCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hnand->State == HAL_NAND_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_NAND_MSP_INIT_CB_ID :
+ hnand->MspInitCallback = pCallback;
+ break;
+ case HAL_NAND_MSP_DEINIT_CB_ID :
+ hnand->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a User NAND Callback
+ * NAND Callback is redirected to the weak predefined callback
+ * @param hnand : NAND handle
+ * @param CallbackId : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID
+ * @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID
+ * @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_NAND_UnRegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_NAND_MSP_INIT_CB_ID :
+ hnand->MspInitCallback = HAL_NAND_MspInit;
+ break;
+ case HAL_NAND_MSP_DEINIT_CB_ID :
+ hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
+ break;
+ case HAL_NAND_IT_CB_ID :
+ hnand->ItCallback = HAL_NAND_ITCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hnand->State == HAL_NAND_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_NAND_MSP_INIT_CB_ID :
+ hnand->MspInitCallback = HAL_NAND_MspInit;
+ break;
+ case HAL_NAND_MSP_DEINIT_CB_ID :
+ hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+#endif /* USE_HAL_NAND_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### NAND Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the NAND interface.
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Enables dynamically NAND ECC feature.
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)
+{
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Update the NAND state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Enable ECC feature */
+ (void)FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);
+
+ /* Update the NAND state */
+ hnand->State = HAL_NAND_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically FMC_NAND ECC feature.
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)
+{
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Update the NAND state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Disable ECC feature */
+ (void)FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);
+
+ /* Update the NAND state */
+ hnand->State = HAL_NAND_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically NAND ECC feature.
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @param ECCval pointer to ECC value
+ * @param Timeout maximum timeout to wait
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the NAND controller state */
+ if (hnand->State == HAL_NAND_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnand->State == HAL_NAND_STATE_READY)
+ {
+ /* Update the NAND state */
+ hnand->State = HAL_NAND_STATE_BUSY;
+
+ /* Get NAND ECC value */
+ status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);
+
+ /* Update the NAND state */
+ hnand->State = HAL_NAND_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @}
+ */
+
+
+/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### NAND State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the NAND controller
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief return the NAND state
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval HAL state
+ */
+HAL_NAND_StateTypeDef HAL_NAND_GetState(const NAND_HandleTypeDef *hnand)
+{
+ return hnand->State;
+}
+
+/**
+ * @brief NAND memory read status
+ * @param hnand pointer to a NAND_HandleTypeDef structure that contains
+ * the configuration information for NAND module.
+ * @retval NAND status
+ */
+uint32_t HAL_NAND_Read_Status(const NAND_HandleTypeDef *hnand)
+{
+ uint32_t data;
+ uint32_t deviceaddress;
+ UNUSED(hnand);
+
+ /* Identify the device address */
+ deviceaddress = NAND_DEVICE;
+
+ /* Send Read status operation command */
+ *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
+
+ /* Read status register data */
+ data = *(__IO uint8_t *)deviceaddress;
+
+ /* Return the status */
+ if ((data & NAND_ERROR) == NAND_ERROR)
+ {
+ return NAND_ERROR;
+ }
+ else if ((data & NAND_READY) == NAND_READY)
+ {
+ return NAND_READY;
+ }
+ else
+ {
+ return NAND_BUSY;
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_NAND_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nor.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nor.c
new file mode 100755
index 0000000..71a7669
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nor.c
@@ -0,0 +1,1642 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_nor.c
+ * @author MCD Application Team
+ * @brief NOR HAL module driver.
+ * This file provides a generic firmware to drive NOR memories mounted
+ * as external device.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a generic layered driver which contains a set of APIs used to
+ control NOR flash memories. It uses the FMC layer functions to interface
+ with NOR devices. This driver is used as follows:
+
+ (+) NOR flash memory configuration sequence using the function HAL_NOR_Init()
+ with control and timing parameters for both normal and extended mode.
+
+ (+) Read NOR flash memory manufacturer code and device IDs using the function
+ HAL_NOR_Read_ID(). The read information is stored in the NOR_ID_TypeDef
+ structure declared by the function caller.
+
+ (+) Access NOR flash memory by read/write data unit operations using the functions
+ HAL_NOR_Read(), HAL_NOR_Program().
+
+ (+) Perform NOR flash erase block/chip operations using the functions
+ HAL_NOR_Erase_Block() and HAL_NOR_Erase_Chip().
+
+ (+) Read the NOR flash CFI (common flash interface) IDs using the function
+ HAL_NOR_Read_CFI(). The read information is stored in the NOR_CFI_TypeDef
+ structure declared by the function caller.
+
+ (+) You can also control the NOR device by calling the control APIs HAL_NOR_WriteOperation_Enable()/
+ HAL_NOR_WriteOperation_Disable() to respectively enable/disable the NOR write operation
+
+ (+) You can monitor the NOR device HAL state by calling the function
+ HAL_NOR_GetState()
+ [..]
+ (@) This driver is a set of generic APIs which handle standard NOR flash operations.
+ If a NOR flash device contains different operations and/or implementations,
+ it should be implemented separately.
+
+ *** NOR HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in NOR HAL driver.
+
+ (+) NOR_WRITE : NOR memory write data to specified address
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_NOR_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions HAL_NOR_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) MspInitCallback : NOR MspInit.
+ (+) MspDeInitCallback : NOR MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function HAL_NOR_UnRegisterCallback() to reset a callback to the default
+ weak (overridden) function. It allows to reset following callbacks:
+ (+) MspInitCallback : NOR MspInit.
+ (+) MspDeInitCallback : NOR MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the HAL_NOR_Init and if the state is HAL_NOR_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (overridden) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (overridden) functions in the HAL_NOR_Init
+ and HAL_NOR_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_NOR_Init and HAL_NOR_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in READY state only.
+ Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
+ in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
+ during the Init/DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_NOR_RegisterCallback before calling HAL_NOR_DeInit
+ or HAL_NOR_Init function.
+
+ When The compilation define USE_HAL_NOR_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (overridden) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_NOR_MODULE_ENABLED
+
+/** @defgroup NOR NOR
+ * @brief NOR driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup NOR_Private_Defines NOR Private Defines
+ * @{
+ */
+
+/* Constants to define address to set to write a command */
+#define NOR_CMD_ADDRESS_FIRST_BYTE (uint16_t)0x0AAA
+#define NOR_CMD_ADDRESS_FIRST_CFI_BYTE (uint16_t)0x00AA
+#define NOR_CMD_ADDRESS_SECOND_BYTE (uint16_t)0x0555
+#define NOR_CMD_ADDRESS_THIRD_BYTE (uint16_t)0x0AAA
+
+#define NOR_CMD_ADDRESS_FIRST (uint16_t)0x0555
+#define NOR_CMD_ADDRESS_FIRST_CFI (uint16_t)0x0055
+#define NOR_CMD_ADDRESS_SECOND (uint16_t)0x02AA
+#define NOR_CMD_ADDRESS_THIRD (uint16_t)0x0555
+#define NOR_CMD_ADDRESS_FOURTH (uint16_t)0x0555
+#define NOR_CMD_ADDRESS_FIFTH (uint16_t)0x02AA
+#define NOR_CMD_ADDRESS_SIXTH (uint16_t)0x0555
+
+/* Constants to define data to program a command */
+#define NOR_CMD_DATA_READ_RESET (uint16_t)0x00F0
+#define NOR_CMD_DATA_FIRST (uint16_t)0x00AA
+#define NOR_CMD_DATA_SECOND (uint16_t)0x0055
+#define NOR_CMD_DATA_AUTO_SELECT (uint16_t)0x0090
+#define NOR_CMD_DATA_PROGRAM (uint16_t)0x00A0
+#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD (uint16_t)0x0080
+#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH (uint16_t)0x00AA
+#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH (uint16_t)0x0055
+#define NOR_CMD_DATA_CHIP_ERASE (uint16_t)0x0010
+#define NOR_CMD_DATA_CFI (uint16_t)0x0098
+
+#define NOR_CMD_DATA_BUFFER_AND_PROG (uint8_t)0x25
+#define NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM (uint8_t)0x29
+#define NOR_CMD_DATA_BLOCK_ERASE (uint8_t)0x30
+
+#define NOR_CMD_READ_ARRAY (uint16_t)0x00FF
+#define NOR_CMD_WORD_PROGRAM (uint16_t)0x0040
+#define NOR_CMD_BUFFERED_PROGRAM (uint16_t)0x00E8
+#define NOR_CMD_CONFIRM (uint16_t)0x00D0
+#define NOR_CMD_BLOCK_ERASE (uint16_t)0x0020
+#define NOR_CMD_BLOCK_UNLOCK (uint16_t)0x0060
+#define NOR_CMD_READ_STATUS_REG (uint16_t)0x0070
+#define NOR_CMD_CLEAR_STATUS_REG (uint16_t)0x0050
+
+/* Mask on NOR STATUS REGISTER */
+#define NOR_MASK_STATUS_DQ4 (uint16_t)0x0010
+#define NOR_MASK_STATUS_DQ5 (uint16_t)0x0020
+#define NOR_MASK_STATUS_DQ6 (uint16_t)0x0040
+#define NOR_MASK_STATUS_DQ7 (uint16_t)0x0080
+
+/* Address of the primary command set */
+#define NOR_ADDRESS_COMMAND_SET (uint16_t)0x0013
+
+/* Command set code assignment (defined in JEDEC JEP137B version may 2004) */
+#define NOR_INTEL_SHARP_EXT_COMMAND_SET (uint16_t)0x0001 /* Supported in this driver */
+#define NOR_AMD_FUJITSU_COMMAND_SET (uint16_t)0x0002 /* Supported in this driver */
+#define NOR_INTEL_STANDARD_COMMAND_SET (uint16_t)0x0003 /* Not Supported in this driver */
+#define NOR_AMD_FUJITSU_EXT_COMMAND_SET (uint16_t)0x0004 /* Not Supported in this driver */
+#define NOR_WINDBOND_STANDARD_COMMAND_SET (uint16_t)0x0006 /* Not Supported in this driver */
+#define NOR_MITSUBISHI_STANDARD_COMMAND_SET (uint16_t)0x0100 /* Not Supported in this driver */
+#define NOR_MITSUBISHI_EXT_COMMAND_SET (uint16_t)0x0101 /* Not Supported in this driver */
+#define NOR_PAGE_WRITE_COMMAND_SET (uint16_t)0x0102 /* Not Supported in this driver */
+#define NOR_INTEL_PERFORMANCE_COMMAND_SET (uint16_t)0x0200 /* Not Supported in this driver */
+#define NOR_INTEL_DATA_COMMAND_SET (uint16_t)0x0210 /* Not Supported in this driver */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/** @defgroup NOR_Private_Variables NOR Private Variables
+ * @{
+ */
+
+static uint32_t uwNORMemoryDataWidth = NOR_MEMORY_8B;
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup NOR_Exported_Functions NOR Exported Functions
+ * @{
+ */
+
+/** @defgroup NOR_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### NOR Initialization and de_initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to initialize/de-initialize
+ the NOR memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Perform the NOR memory Initialization sequence
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param Timing pointer to NOR control timing structure
+ * @param ExtTiming pointer to NOR extended mode timing structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Init(NOR_HandleTypeDef *hnor, FMC_NORSRAM_TimingTypeDef *Timing,
+ FMC_NORSRAM_TimingTypeDef *ExtTiming)
+{
+ uint32_t deviceaddress;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR handle parameter */
+ if (hnor == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hnor->State == HAL_NOR_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hnor->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
+ if (hnor->MspInitCallback == NULL)
+ {
+ hnor->MspInitCallback = HAL_NOR_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hnor->MspInitCallback(hnor);
+#else
+ /* Initialize the low level hardware (MSP) */
+ HAL_NOR_MspInit(hnor);
+#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
+ }
+
+ /* Initialize NOR control Interface */
+ (void)FMC_NORSRAM_Init(hnor->Instance, &(hnor->Init));
+
+ /* Initialize NOR timing Interface */
+ (void)FMC_NORSRAM_Timing_Init(hnor->Instance, Timing, hnor->Init.NSBank);
+
+ /* Initialize NOR extended mode timing Interface */
+ (void)FMC_NORSRAM_Extended_Timing_Init(hnor->Extended, ExtTiming,
+ hnor->Init.NSBank, hnor->Init.ExtendedMode);
+
+ /* Enable the NORSRAM device */
+ __FMC_NORSRAM_ENABLE(hnor->Instance, hnor->Init.NSBank);
+
+ /* Initialize NOR Memory Data Width*/
+ if (hnor->Init.MemoryDataWidth == FMC_NORSRAM_MEM_BUS_WIDTH_8)
+ {
+ uwNORMemoryDataWidth = NOR_MEMORY_8B;
+ }
+ else
+ {
+ uwNORMemoryDataWidth = NOR_MEMORY_16B;
+ }
+
+ /* Enable FMC Peripheral */
+ __FMC_ENABLE();
+
+ /* Initialize the NOR controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ if (hnor->Init.WriteOperation == FMC_WRITE_OPERATION_DISABLE)
+ {
+ (void)FMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_PROTECTED;
+ }
+ else
+ {
+ /* Get the value of the command set */
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
+ NOR_CMD_DATA_CFI);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
+ }
+
+ hnor->CommandSet = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET);
+
+ status = HAL_NOR_ReturnToReadMode(hnor);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Perform NOR memory De-Initialization sequence
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_DeInit(NOR_HandleTypeDef *hnor)
+{
+#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
+ if (hnor->MspDeInitCallback == NULL)
+ {
+ hnor->MspDeInitCallback = HAL_NOR_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hnor->MspDeInitCallback(hnor);
+#else
+ /* De-Initialize the low level hardware (MSP) */
+ HAL_NOR_MspDeInit(hnor);
+#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
+
+ /* Configure the NOR registers with their reset values */
+ (void)FMC_NORSRAM_DeInit(hnor->Instance, hnor->Extended, hnor->Init.NSBank);
+
+ /* Reset the NOR controller state */
+ hnor->State = HAL_NOR_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hnor);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief NOR MSP Init
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval None
+ */
+__weak void HAL_NOR_MspInit(NOR_HandleTypeDef *hnor)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hnor);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_NOR_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief NOR MSP DeInit
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval None
+ */
+__weak void HAL_NOR_MspDeInit(NOR_HandleTypeDef *hnor)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hnor);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_NOR_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief NOR MSP Wait for Ready/Busy signal
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param Timeout Maximum timeout value
+ * @retval None
+ */
+__weak void HAL_NOR_MspWait(NOR_HandleTypeDef *hnor, uint32_t Timeout)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hnor);
+ UNUSED(Timeout);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_NOR_MspWait could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup NOR_Exported_Functions_Group2 Input and Output functions
+ * @brief Input Output and memory control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### NOR Input and Output functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to use and control the NOR memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Read NOR flash IDs
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param pNOR_ID pointer to NOR ID structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Read_ID(NOR_HandleTypeDef *hnor, NOR_IDTypeDef *pNOR_ID)
+{
+ uint32_t deviceaddress;
+ HAL_NOR_StateTypeDef state;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (state == HAL_NOR_STATE_PROTECTED)
+ {
+ return HAL_ERROR;
+ }
+ else if (state == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send read ID command */
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
+ NOR_CMD_DATA_AUTO_SELECT);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
+ NOR_CMD_DATA_AUTO_SELECT);
+ }
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ NOR_WRITE(deviceaddress, NOR_CMD_DATA_AUTO_SELECT);
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_ERROR)
+ {
+ /* Read the NOR IDs */
+ pNOR_ID->Manufacturer_Code = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, MC_ADDRESS);
+ pNOR_ID->Device_Code1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
+ DEVICE_CODE1_ADDR);
+ pNOR_ID->Device_Code2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
+ DEVICE_CODE2_ADDR);
+ pNOR_ID->Device_Code3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
+ DEVICE_CODE3_ADDR);
+ }
+
+ /* Check the NOR controller state */
+ hnor->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Returns the NOR memory to Read mode.
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_ReturnToReadMode(NOR_HandleTypeDef *hnor)
+{
+ uint32_t deviceaddress;
+ HAL_NOR_StateTypeDef state;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (state == HAL_NOR_STATE_PROTECTED)
+ {
+ return HAL_ERROR;
+ }
+ else if (state == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ NOR_WRITE(deviceaddress, NOR_CMD_DATA_READ_RESET);
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY);
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ /* Check the NOR controller state */
+ hnor->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Read data from NOR memory
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param pAddress pointer to Device address
+ * @param pData pointer to read data
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Read(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData)
+{
+ uint32_t deviceaddress;
+ HAL_NOR_StateTypeDef state;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (state == HAL_NOR_STATE_PROTECTED)
+ {
+ return HAL_ERROR;
+ }
+ else if (state == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send read data command */
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
+ NOR_CMD_DATA_READ_RESET);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
+ NOR_CMD_DATA_READ_RESET);
+ }
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ NOR_WRITE(pAddress, NOR_CMD_READ_ARRAY);
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_ERROR)
+ {
+ /* Read the data */
+ *pData = (uint16_t)(*(__IO uint32_t *)pAddress);
+ }
+
+ /* Check the NOR controller state */
+ hnor->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Program data to NOR memory
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param pAddress Device address
+ * @param pData pointer to the data to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Program(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData)
+{
+ uint32_t deviceaddress;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ if (hnor->State == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnor->State == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send program data command */
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
+ NOR_CMD_DATA_PROGRAM);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_PROGRAM);
+ }
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ NOR_WRITE(pAddress, NOR_CMD_WORD_PROGRAM);
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_ERROR)
+ {
+ /* Write the data */
+ NOR_WRITE(pAddress, *pData);
+ }
+
+ /* Check the NOR controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Reads a half-word buffer from the NOR memory.
+ * @param hnor pointer to the NOR handle
+ * @param uwAddress NOR memory internal address to read from.
+ * @param pData pointer to the buffer that receives the data read from the
+ * NOR memory.
+ * @param uwBufferSize number of Half word to read.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_ReadBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData,
+ uint32_t uwBufferSize)
+{
+ uint32_t deviceaddress;
+ uint32_t size = uwBufferSize;
+ uint32_t address = uwAddress;
+ uint16_t *data = pData;
+ HAL_NOR_StateTypeDef state;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (state == HAL_NOR_STATE_PROTECTED)
+ {
+ return HAL_ERROR;
+ }
+ else if (state == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send read data command */
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
+ NOR_CMD_DATA_READ_RESET);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
+ NOR_CMD_DATA_READ_RESET);
+ }
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY);
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_ERROR)
+ {
+ /* Read buffer */
+ while (size > 0U)
+ {
+ *data = *(__IO uint16_t *)address;
+ data++;
+ address += 2U;
+ size--;
+ }
+ }
+
+ /* Check the NOR controller state */
+ hnor->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Writes a half-word buffer to the NOR memory. This function must be used
+ only with S29GL128P NOR memory.
+ * @param hnor pointer to the NOR handle
+ * @param uwAddress NOR memory internal start write address
+ * @param pData pointer to source data buffer.
+ * @param uwBufferSize Size of the buffer to write
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_ProgramBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData,
+ uint32_t uwBufferSize)
+{
+ uint16_t *p_currentaddress;
+ const uint16_t *p_endaddress;
+ uint16_t *data = pData;
+ uint32_t deviceaddress;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ if (hnor->State == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnor->State == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Initialize variables */
+ p_currentaddress = (uint16_t *)(deviceaddress + uwAddress);
+ p_endaddress = (uint16_t *)(deviceaddress + uwAddress + (2U * (uwBufferSize - 1U)));
+
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ /* Issue unlock command sequence */
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ }
+ else
+ {
+ /* Issue unlock command sequence */
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ }
+ /* Write Buffer Load Command */
+ NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG);
+ NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U));
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ /* Write Buffer Load Command */
+ NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_BUFFERED_PROGRAM);
+ NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U));
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ if (status != HAL_ERROR)
+ {
+ /* Load Data into NOR Buffer */
+ while (p_currentaddress <= p_endaddress)
+ {
+ NOR_WRITE(p_currentaddress, *data);
+
+ data++;
+ p_currentaddress ++;
+ }
+
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM);
+ }
+ else /* => hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET */
+ {
+ NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_CONFIRM);
+ }
+ }
+
+ /* Check the NOR controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+
+}
+
+/**
+ * @brief Erase the specified block of the NOR memory
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param BlockAddress Block to erase address
+ * @param Address Device address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Erase_Block(NOR_HandleTypeDef *hnor, uint32_t BlockAddress, uint32_t Address)
+{
+ uint32_t deviceaddress;
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the NOR controller state */
+ if (hnor->State == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnor->State == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send block erase command sequence */
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH);
+ }
+ NOR_WRITE((uint32_t)(BlockAddress + Address), NOR_CMD_DATA_BLOCK_ERASE);
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_UNLOCK);
+ NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM);
+ NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_ERASE);
+ NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM);
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ /* Check the NOR memory status and update the controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+
+}
+
+/**
+ * @brief Erase the entire NOR chip.
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param Address Device address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Erase_Chip(NOR_HandleTypeDef *hnor, uint32_t Address)
+{
+ uint32_t deviceaddress;
+ HAL_StatusTypeDef status = HAL_OK;
+ UNUSED(Address);
+
+ /* Check the NOR controller state */
+ if (hnor->State == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hnor->State == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send NOR chip erase command sequence */
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
+ NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
+ NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH),
+ NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH);
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SIXTH),
+ NOR_CMD_DATA_CHIP_ERASE);
+ }
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_ERROR;
+ }
+
+ /* Check the NOR memory status and update the controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Read NOR flash CFI IDs
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param pNOR_CFI pointer to NOR CFI IDs structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_Read_CFI(NOR_HandleTypeDef *hnor, NOR_CFITypeDef *pNOR_CFI)
+{
+ uint32_t deviceaddress;
+ HAL_NOR_StateTypeDef state;
+
+ /* Check the NOR controller state */
+ state = hnor->State;
+ if (state == HAL_NOR_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (state == HAL_NOR_STATE_PROTECTED)
+ {
+ return HAL_ERROR;
+ }
+ else if (state == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Select the NOR device address */
+ if (hnor->Init.NSBank == FMC_NORSRAM_BANK1)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS1;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS2;
+ }
+ else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3)
+ {
+ deviceaddress = NOR_MEMORY_ADRESS3;
+ }
+ else /* FMC_NORSRAM_BANK4 */
+ {
+ deviceaddress = NOR_MEMORY_ADRESS4;
+ }
+
+ /* Send read CFI query command */
+ if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
+ NOR_CMD_DATA_CFI);
+ }
+ else
+ {
+ NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
+ }
+ /* read the NOR CFI information */
+ pNOR_CFI->CFI_1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI1_ADDRESS);
+ pNOR_CFI->CFI_2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI2_ADDRESS);
+ pNOR_CFI->CFI_3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI3_ADDRESS);
+ pNOR_CFI->CFI_4 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI4_ADDRESS);
+
+ /* Check the NOR controller state */
+ hnor->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User NOR Callback
+ * To be used to override the weak predefined callback
+ * @param hnor : NOR handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID
+ * @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_NOR_RegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId,
+ pNOR_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_NOR_StateTypeDef state;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ state = hnor->State;
+ if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_NOR_MSP_INIT_CB_ID :
+ hnor->MspInitCallback = pCallback;
+ break;
+ case HAL_NOR_MSP_DEINIT_CB_ID :
+ hnor->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a User NOR Callback
+ * NOR Callback is redirected to the weak predefined callback
+ * @param hnor : NOR handle
+ * @param CallbackId : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID
+ * @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_NOR_UnRegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_NOR_StateTypeDef state;
+
+ state = hnor->State;
+ if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_NOR_MSP_INIT_CB_ID :
+ hnor->MspInitCallback = HAL_NOR_MspInit;
+ break;
+ case HAL_NOR_MSP_DEINIT_CB_ID :
+ hnor->MspDeInitCallback = HAL_NOR_MspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
+
+/**
+ * @}
+ */
+
+/** @defgroup NOR_Exported_Functions_Group3 NOR Control functions
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### NOR Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the NOR interface.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables dynamically NOR write operation.
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_WriteOperation_Enable(NOR_HandleTypeDef *hnor)
+{
+ /* Check the NOR controller state */
+ if (hnor->State == HAL_NOR_STATE_PROTECTED)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Enable write operation */
+ (void)FMC_NORSRAM_WriteOperation_Enable(hnor->Instance, hnor->Init.NSBank);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically NOR write operation.
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_NOR_WriteOperation_Disable(NOR_HandleTypeDef *hnor)
+{
+ /* Check the NOR controller state */
+ if (hnor->State == HAL_NOR_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hnor);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_BUSY;
+
+ /* Disable write operation */
+ (void)FMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank);
+
+ /* Update the NOR controller state */
+ hnor->State = HAL_NOR_STATE_PROTECTED;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hnor);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup NOR_Exported_Functions_Group4 NOR State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### NOR State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the NOR controller
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief return the NOR controller state
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @retval NOR controller state
+ */
+HAL_NOR_StateTypeDef HAL_NOR_GetState(const NOR_HandleTypeDef *hnor)
+{
+ return hnor->State;
+}
+
+/**
+ * @brief Returns the NOR operation status.
+ * @param hnor pointer to a NOR_HandleTypeDef structure that contains
+ * the configuration information for NOR module.
+ * @param Address Device address
+ * @param Timeout NOR programming Timeout
+ * @retval NOR_Status The returned value can be: HAL_NOR_STATUS_SUCCESS, HAL_NOR_STATUS_ERROR
+ * or HAL_NOR_STATUS_TIMEOUT
+ */
+HAL_NOR_StatusTypeDef HAL_NOR_GetStatus(NOR_HandleTypeDef *hnor, uint32_t Address, uint32_t Timeout)
+{
+ HAL_NOR_StatusTypeDef status = HAL_NOR_STATUS_ONGOING;
+ uint16_t tmpsr1;
+ uint16_t tmpsr2;
+ uint32_t tickstart;
+
+ /* Poll on NOR memory Ready/Busy signal ------------------------------------*/
+ HAL_NOR_MspWait(hnor, Timeout);
+
+ /* Get the NOR memory operation status -------------------------------------*/
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
+ {
+ while ((status != HAL_NOR_STATUS_SUCCESS) && (status != HAL_NOR_STATUS_TIMEOUT))
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ status = HAL_NOR_STATUS_TIMEOUT;
+ }
+ }
+
+ /* Read NOR status register (DQ6 and DQ5) */
+ tmpsr1 = *(__IO uint16_t *)Address;
+ tmpsr2 = *(__IO uint16_t *)Address;
+
+ /* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */
+ if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6))
+ {
+ return HAL_NOR_STATUS_SUCCESS ;
+ }
+
+ if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5)
+ {
+ status = HAL_NOR_STATUS_ONGOING;
+ }
+
+ tmpsr1 = *(__IO uint16_t *)Address;
+ tmpsr2 = *(__IO uint16_t *)Address;
+
+ /* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */
+ if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6))
+ {
+ return HAL_NOR_STATUS_SUCCESS;
+ }
+ if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5)
+ {
+ return HAL_NOR_STATUS_ERROR;
+ }
+ }
+ }
+ else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
+ {
+ do
+ {
+ NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
+ tmpsr2 = *(__IO uint16_t *)(Address);
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_NOR_STATUS_TIMEOUT;
+ }
+ }
+ } while ((tmpsr2 & NOR_MASK_STATUS_DQ7) == 0U);
+
+ NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
+ tmpsr1 = *(__IO uint16_t *)(Address);
+ if ((tmpsr1 & (NOR_MASK_STATUS_DQ5 | NOR_MASK_STATUS_DQ4)) != 0U)
+ {
+ /* Clear the Status Register */
+ NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
+ status = HAL_NOR_STATUS_ERROR;
+ }
+ else
+ {
+ status = HAL_NOR_STATUS_SUCCESS;
+ }
+ }
+ else
+ {
+ /* Primary command set not supported by the driver */
+ status = HAL_NOR_STATUS_ERROR;
+ }
+
+ /* Return the operation status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_NOR_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c
new file mode 100755
index 0000000..1fc5550
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c
@@ -0,0 +1,2347 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_pcd.c
+ * @author MCD Application Team
+ * @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
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ The PCD HAL driver can be used as follows:
+
+ (#) Declare a PCD_HandleTypeDef handle structure, for example:
+ PCD_HandleTypeDef hpcd;
+
+ (#) Fill parameters of Init structure in HCD handle
+
+ (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
+
+ (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
+ (##) Enable the PCD/USB Low Level interface clock using
+ (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
+ (+++) __HAL_RCC_USB_OTG_HS_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 PCD transmission and reception:
+ (##) HAL_PCD_Start();
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PCD PCD
+ * @brief PCD HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+
+/* 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
+ * @{
+ */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup PCD_Exported_Functions PCD Exported Functions
+ * @{
+ */
+
+/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the PCD according to the specified
+ * parameters in the PCD_InitTypeDef and initialize the associated handle.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
+{
+ uint8_t i;
+
+ /* Check the PCD handle allocation */
+ if (hpcd == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
+
+ if (hpcd->State == HAL_PCD_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hpcd->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->SOFCallback = HAL_PCD_SOFCallback;
+ hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
+ hpcd->ResetCallback = HAL_PCD_ResetCallback;
+ hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
+ hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
+ hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
+ hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
+ hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
+ hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
+ hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
+ hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
+ hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
+ hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
+
+ if (hpcd->MspInitCallback == NULL)
+ {
+ hpcd->MspInitCallback = HAL_PCD_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hpcd->MspInitCallback(hpcd);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC... */
+ HAL_PCD_MspInit(hpcd);
+#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
+ }
+
+ hpcd->State = HAL_PCD_STATE_BUSY;
+
+ /* Disable the Interrupts */
+ __HAL_PCD_DISABLE(hpcd);
+
+ /*Init the Core (common init.) */
+ if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
+ {
+ hpcd->State = HAL_PCD_STATE_ERROR;
+ return HAL_ERROR;
+ }
+
+ /* Force Device Mode */
+ if (USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE) != HAL_OK)
+ {
+ hpcd->State = HAL_PCD_STATE_ERROR;
+ return HAL_ERROR;
+ }
+
+ /* Init endpoints structures */
+ for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
+ {
+ /* Init ep structure */
+ hpcd->IN_ep[i].is_in = 1U;
+ 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 = 0U;
+ hpcd->IN_ep[i].xfer_buff = 0U;
+ hpcd->IN_ep[i].xfer_len = 0U;
+ }
+
+ for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
+ {
+ hpcd->OUT_ep[i].is_in = 0U;
+ hpcd->OUT_ep[i].num = i;
+ /* Control until ep is activated */
+ hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
+ hpcd->OUT_ep[i].maxpacket = 0U;
+ hpcd->OUT_ep[i].xfer_buff = 0U;
+ hpcd->OUT_ep[i].xfer_len = 0U;
+ }
+
+ /* Init Device */
+ if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
+ {
+ hpcd->State = HAL_PCD_STATE_ERROR;
+ return HAL_ERROR;
+ }
+
+ hpcd->USB_Address = 0U;
+ hpcd->State = HAL_PCD_STATE_READY;
+
+ /* Activate LPM */
+ if (hpcd->Init.lpm_enable == 1U)
+ {
+ (void)HAL_PCDEx_ActivateLPM(hpcd);
+ }
+
+ (void)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 */
+ if (USB_StopDevice(hpcd->Instance) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ if (hpcd->MspDeInitCallback == NULL)
+ {
+ hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit */
+ }
+
+ /* DeInit the low level hardware */
+ hpcd->MspDeInitCallback(hpcd);
+#else
+ /* DeInit the low level hardware: CLOCK, NVIC.*/
+ HAL_PCD_MspDeInit(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+ hpcd->State = HAL_PCD_STATE_RESET;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the PCD MSP.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes PCD MSP.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+/**
+ * @brief Register a User USB PCD Callback
+ * To be used instead of the weak predefined callback
+ * @param hpcd USB PCD handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
+ * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
+ * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
+ * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
+ * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
+ * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
+ * @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
+ * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
+ * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
+ HAL_PCD_CallbackIDTypeDef CallbackID,
+ pPCD_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PCD_SOF_CB_ID :
+ hpcd->SOFCallback = pCallback;
+ break;
+
+ case HAL_PCD_SETUPSTAGE_CB_ID :
+ hpcd->SetupStageCallback = pCallback;
+ break;
+
+ case HAL_PCD_RESET_CB_ID :
+ hpcd->ResetCallback = pCallback;
+ break;
+
+ case HAL_PCD_SUSPEND_CB_ID :
+ hpcd->SuspendCallback = pCallback;
+ break;
+
+ case HAL_PCD_RESUME_CB_ID :
+ hpcd->ResumeCallback = pCallback;
+ break;
+
+ case HAL_PCD_CONNECT_CB_ID :
+ hpcd->ConnectCallback = pCallback;
+ break;
+
+ case HAL_PCD_DISCONNECT_CB_ID :
+ hpcd->DisconnectCallback = pCallback;
+ break;
+
+ case HAL_PCD_MSPINIT_CB_ID :
+ hpcd->MspInitCallback = pCallback;
+ break;
+
+ case HAL_PCD_MSPDEINIT_CB_ID :
+ hpcd->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hpcd->State == HAL_PCD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PCD_MSPINIT_CB_ID :
+ hpcd->MspInitCallback = pCallback;
+ break;
+
+ case HAL_PCD_MSPDEINIT_CB_ID :
+ hpcd->MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+ return status;
+}
+
+/**
+ * @brief Unregister an USB PCD Callback
+ * USB PCD callback is redirected to the weak predefined callback
+ * @param hpcd USB PCD handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
+ * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
+ * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
+ * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
+ * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
+ * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
+ * @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
+ * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
+ * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ /* Setup Legacy weak Callbacks */
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PCD_SOF_CB_ID :
+ hpcd->SOFCallback = HAL_PCD_SOFCallback;
+ break;
+
+ case HAL_PCD_SETUPSTAGE_CB_ID :
+ hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
+ break;
+
+ case HAL_PCD_RESET_CB_ID :
+ hpcd->ResetCallback = HAL_PCD_ResetCallback;
+ break;
+
+ case HAL_PCD_SUSPEND_CB_ID :
+ hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
+ break;
+
+ case HAL_PCD_RESUME_CB_ID :
+ hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
+ break;
+
+ case HAL_PCD_CONNECT_CB_ID :
+ hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
+ break;
+
+ case HAL_PCD_DISCONNECT_CB_ID :
+ hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
+ break;
+
+ case HAL_PCD_MSPINIT_CB_ID :
+ hpcd->MspInitCallback = HAL_PCD_MspInit;
+ break;
+
+ case HAL_PCD_MSPDEINIT_CB_ID :
+ hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hpcd->State == HAL_PCD_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_PCD_MSPINIT_CB_ID :
+ hpcd->MspInitCallback = HAL_PCD_MspInit;
+ break;
+
+ case HAL_PCD_MSPDEINIT_CB_ID :
+ hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
+ break;
+
+ default :
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+ return status;
+}
+
+/**
+ * @brief Register USB PCD Data OUT Stage Callback
+ * To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
+ * @param hpcd PCD handle
+ * @param pCallback pointer to the USB PCD Data OUT Stage Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
+ pPCD_DataOutStageCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->DataOutStageCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Unregister the USB PCD Data OUT Stage Callback
+ * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Register USB PCD Data IN Stage Callback
+ * To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
+ * @param hpcd PCD handle
+ * @param pCallback pointer to the USB PCD Data IN Stage Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
+ pPCD_DataInStageCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->DataInStageCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Unregister the USB PCD Data IN Stage Callback
+ * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Register USB PCD Iso OUT incomplete Callback
+ * To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
+ * @param hpcd PCD handle
+ * @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
+ pPCD_IsoOutIncpltCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->ISOOUTIncompleteCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Unregister the USB PCD Iso OUT incomplete Callback
+ * USB PCD Iso OUT incomplete Callback is redirected
+ * to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Register USB PCD Iso IN incomplete Callback
+ * To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
+ * @param hpcd PCD handle
+ * @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
+ pPCD_IsoInIncpltCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->ISOINIncompleteCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Unregister the USB PCD Iso IN incomplete Callback
+ * USB PCD Iso IN incomplete Callback is redirected
+ * to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback */
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Register USB PCD BCD Callback
+ * To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
+ * @param hpcd PCD handle
+ * @param pCallback pointer to the USB PCD BCD Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->BCDCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Unregister the USB PCD BCD Callback
+ * USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback */
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Register USB PCD LPM Callback
+ * To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
+ * @param hpcd PCD handle
+ * @param pCallback pointer to the USB PCD LPM Callback function
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->LPMCallback = pCallback;
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+
+/**
+ * @brief Unregister the USB PCD LPM Callback
+ * USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hpcd);
+
+ if (hpcd->State == HAL_PCD_STATE_READY)
+ {
+ hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback */
+ }
+ else
+ {
+ /* Update the error code */
+ hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
+
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hpcd);
+
+ return status;
+}
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
+ * @brief Data transfers functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to manage the PCD data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start the USB device
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ __HAL_LOCK(hpcd);
+
+ if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+ (hpcd->Init.battery_charging_enable == 1U))
+ {
+ /* Enable USB Transceiver */
+ USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+ }
+
+ __HAL_PCD_ENABLE(hpcd);
+ (void)USB_DevConnect(hpcd->Instance);
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the USB device.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ __HAL_LOCK(hpcd);
+ __HAL_PCD_DISABLE(hpcd);
+ (void)USB_DevDisconnect(hpcd->Instance);
+
+ (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
+
+ if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+ (hpcd->Init.battery_charging_enable == 1U))
+ {
+ /* Disable USB Transceiver */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+ }
+
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+ * @brief Handles PCD interrupt request.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ USB_OTG_EPTypeDef *ep;
+ uint32_t i;
+ uint32_t ep_intr;
+ uint32_t epint;
+ uint32_t epnum;
+ uint32_t fifoemptymsk;
+ uint32_t RegVal;
+
+ /* 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;
+ }
+
+ /* store current frame number */
+ hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;
+
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
+ {
+ /* incorrect mode, acknowledge the interrupt */
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
+ }
+
+ /* Handle RxQLevel Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
+ {
+ USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+
+ RegVal = USBx->GRXSTSP;
+
+ ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];
+
+ if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
+ {
+ if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U)
+ {
+ (void)USB_ReadPacket(USBx, ep->xfer_buff,
+ (uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));
+
+ ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
+ ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
+ }
+ }
+ else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
+ {
+ (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
+ ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
+ }
+ else
+ {
+ /* ... */
+ }
+
+ USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
+ }
+
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
+ {
+ epnum = 0U;
+
+ /* Read in the device interrupt bits */
+ ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
+
+ while (ep_intr != 0U)
+ {
+ if ((ep_intr & 0x1U) != 0U)
+ {
+ epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
+
+ if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
+ (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
+ }
+
+ if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
+ /* Class B setup phase done for previous decoded setup */
+ (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
+ }
+
+ if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
+ }
+
+ /* Clear OUT Endpoint disable interrupt */
+ if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
+ {
+ if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF)
+ {
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
+ }
+
+ ep = &hpcd->OUT_ep[epnum];
+
+ if (ep->is_iso_incomplete == 1U)
+ {
+ ep->is_iso_incomplete = 0U;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
+#else
+ HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
+ }
+
+ /* Clear Status Phase Received interrupt */
+ if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
+ }
+
+ /* Clear OUT NAK interrupt */
+ if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
+ }
+ }
+ epnum++;
+ ep_intr >>= 1U;
+ }
+ }
+
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
+ {
+ /* Read in the device interrupt bits */
+ ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
+
+ epnum = 0U;
+
+ while (ep_intr != 0U)
+ {
+ if ((ep_intr & 0x1U) != 0U) /* In ITR */
+ {
+ epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
+
+ if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
+ {
+ fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
+ USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
+
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
+
+ if (hpcd->Init.dma_enable == 1U)
+ {
+ hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
+
+ /* this is ZLP, so prepare EP0 for next setup */
+ if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
+ {
+ /* prepare to rx more setup packets */
+ (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
+ }
+ }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
+#else
+ HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ 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)
+ {
+ (void)USB_FlushTxFifo(USBx, epnum);
+
+ ep = &hpcd->IN_ep[epnum];
+
+ if (ep->is_iso_incomplete == 1U)
+ {
+ ep->is_iso_incomplete = 0U;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
+#else
+ HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+
+ CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
+ }
+ if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
+ {
+ (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
+ }
+ }
+ epnum++;
+ ep_intr >>= 1U;
+ }
+ }
+
+ /* 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;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
+#else
+ HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->ResumeCallback(hpcd);
+#else
+ HAL_PCD_ResumeCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+
+ __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)
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->SuspendCallback(hpcd);
+#else
+ HAL_PCD_SuspendCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ __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) >> 2U;
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
+#else
+ HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->SuspendCallback(hpcd);
+#else
+ HAL_PCD_SuspendCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Handle Reset Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
+ {
+ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
+ (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
+
+ for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
+ {
+ USBx_INEP(i)->DIEPINT = 0xFB7FU;
+ USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
+ USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
+ USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
+ USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
+ }
+ USBx_DEVICE->DAINTMSK |= 0x10001U;
+
+ if (hpcd->Init.use_dedicated_ep1 != 0U)
+ {
+ 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 |
+ USB_OTG_DOEPMSK_OTEPSPRM |
+ USB_OTG_DOEPMSK_NAKM;
+
+ 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 */
+ (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)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))
+ {
+ (void)USB_ActivateSetup(hpcd->Instance);
+ hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
+
+ /* Set USB Turnaround time */
+ (void)USB_SetTurnaroundTime(hpcd->Instance,
+ HAL_RCC_GetHCLKFreq(),
+ (uint8_t)hpcd->Init.speed);
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->ResetCallback(hpcd);
+#else
+ HAL_PCD_ResetCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
+ }
+
+ /* Handle SOF Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->SOFCallback(hpcd);
+#else
+ HAL_PCD_SOFCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
+ }
+
+ /* Handle Global OUT NAK effective Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF))
+ {
+ USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;
+
+ for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
+ {
+ if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U)
+ {
+ /* disable the EP */
+ USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_SNAK);
+ USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_EPDIS);
+ }
+ }
+ }
+
+ /* Handle Incomplete ISO IN Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
+ {
+ for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
+ {
+ RegVal = USBx_INEP(epnum)->DIEPCTL;
+
+ if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&
+ ((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA))
+ {
+ hpcd->IN_ep[epnum].is_iso_incomplete = 1U;
+
+ /* Abort current transaction and disable the EP */
+ (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));
+ }
+ }
+
+ __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))
+ {
+ for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
+ {
+ RegVal = USBx_OUTEP(epnum)->DOEPCTL;
+
+ if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&
+ ((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&
+ (((RegVal & (0x1UL << 16)) >> 16U) == (hpcd->FrameNumber & 0x1U)))
+ {
+ hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;
+
+ USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;
+
+ if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
+ {
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
+ break;
+ }
+ }
+ }
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
+ }
+
+ /* Handle Connection event Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->ConnectCallback(hpcd);
+#else
+ HAL_PCD_ConnectCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+ __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
+ }
+
+ /* Handle Disconnection event Interrupt */
+ if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
+ {
+ RegVal = hpcd->Instance->GOTGINT;
+
+ if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->DisconnectCallback(hpcd);
+#else
+ HAL_PCD_DisconnectCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ hpcd->Instance->GOTGINT |= RegVal;
+ }
+ }
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+
+/**
+ * @brief Data OUT stage callback.
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_DataOutStageCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Data IN stage callback
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_DataInStageCallback could be implemented in the user file
+ */
+}
+/**
+ * @brief Setup stage callback
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_SetupStageCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief USB Start Of Frame callback.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_SOFCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief USB Reset callback.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ResetCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Suspend event callback.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_SuspendCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Resume event callback.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ResumeCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Incomplete ISO OUT callback.
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Incomplete ISO IN callback.
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval None
+ */
+__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(epnum);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Connection event callback.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_ConnectCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Disconnection event callback.
+ * @param hpcd PCD handle
+ * @retval None
+ */
+__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCD_DisconnectCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the PCD data
+ transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Connect the USB device
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ __HAL_LOCK(hpcd);
+
+ if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+ (hpcd->Init.battery_charging_enable == 1U))
+ {
+ /* Enable USB Transceiver */
+ USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+ }
+ (void)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)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ __HAL_LOCK(hpcd);
+ (void)USB_DevDisconnect(hpcd->Instance);
+
+ if (((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) != 0U) &&
+ (hpcd->Init.battery_charging_enable == 1U))
+ {
+ /* Disable USB Transceiver */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+ }
+
+ __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);
+ hpcd->USB_Address = address;
+ (void)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;
+ PCD_EPTypeDef *ep;
+
+ if ((ep_addr & 0x80U) == 0x80U)
+ {
+ ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 1U;
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 0U;
+ }
+
+ ep->num = ep_addr & EP_ADDR_MSK;
+ ep->maxpacket = (uint32_t)ep_mps & 0x7FFU;
+ ep->type = ep_type;
+
+ if (ep->is_in != 0U)
+ {
+ /* Assign a Tx FIFO */
+ ep->tx_fifo_num = ep->num;
+ }
+
+ /* Set initial data PID. */
+ if (ep_type == EP_TYPE_BULK)
+ {
+ ep->data_pid_start = 0U;
+ }
+
+ __HAL_LOCK(hpcd);
+ (void)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)
+{
+ PCD_EPTypeDef *ep;
+
+ if ((ep_addr & 0x80U) == 0x80U)
+ {
+ ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 1U;
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 0U;
+ }
+ ep->num = ep_addr & EP_ADDR_MSK;
+
+ __HAL_LOCK(hpcd);
+ (void)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)
+{
+ PCD_EPTypeDef *ep;
+
+ ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+
+ /*setup and start the Xfer */
+ ep->xfer_buff = pBuf;
+ ep->xfer_len = len;
+ ep->xfer_count = 0U;
+ ep->is_in = 0U;
+ ep->num = ep_addr & EP_ADDR_MSK;
+
+ if (hpcd->Init.dma_enable == 1U)
+ {
+ ep->dma_addr = (uint32_t)pBuf;
+ }
+
+ (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get Received Data Size
+ * @param hpcd PCD handle
+ * @param ep_addr endpoint address
+ * @retval Data Size
+ */
+uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr)
+{
+ return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].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)
+{
+ PCD_EPTypeDef *ep;
+
+ ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+
+ /*setup and start the Xfer */
+ ep->xfer_buff = pBuf;
+ ep->xfer_len = len;
+ ep->xfer_count = 0U;
+ ep->is_in = 1U;
+ ep->num = ep_addr & EP_ADDR_MSK;
+
+ if (hpcd->Init.dma_enable == 1U)
+ {
+ ep->dma_addr = (uint32_t)pBuf;
+ }
+
+ (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
+
+ 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)
+{
+ PCD_EPTypeDef *ep;
+
+ if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
+ {
+ return HAL_ERROR;
+ }
+
+ if ((0x80U & ep_addr) == 0x80U)
+ {
+ ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 1U;
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr];
+ ep->is_in = 0U;
+ }
+
+ ep->is_stall = 1U;
+ ep->num = ep_addr & EP_ADDR_MSK;
+
+ __HAL_LOCK(hpcd);
+
+ (void)USB_EPSetStall(hpcd->Instance, ep);
+
+ if ((ep_addr & EP_ADDR_MSK) == 0U)
+ {
+ (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)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)
+{
+ PCD_EPTypeDef *ep;
+
+ if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
+ {
+ return HAL_ERROR;
+ }
+
+ if ((0x80U & ep_addr) == 0x80U)
+ {
+ ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 1U;
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+ ep->is_in = 0U;
+ }
+
+ ep->is_stall = 0U;
+ ep->num = ep_addr & EP_ADDR_MSK;
+
+ __HAL_LOCK(hpcd);
+ (void)USB_EPClearStall(hpcd->Instance, ep);
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Abort an USB EP transaction.
+ * @param hpcd PCD handle
+ * @param ep_addr endpoint address
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
+{
+ HAL_StatusTypeDef ret;
+ PCD_EPTypeDef *ep;
+
+ if ((0x80U & ep_addr) == 0x80U)
+ {
+ ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
+ }
+
+ /* Stop Xfer */
+ ret = USB_EPStopXfer(hpcd->Instance, ep);
+
+ return ret;
+}
+
+/**
+ * @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 & 0x80U) == 0x80U)
+ {
+ (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
+ }
+ else
+ {
+ (void)USB_FlushRxFifo(hpcd->Instance);
+ }
+
+ __HAL_UNLOCK(hpcd);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Activate remote wakeup signalling
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
+{
+ return (USB_ActivateRemoteWakeup(hpcd->Instance));
+}
+
+/**
+ * @brief De-activate remote wakeup signalling.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
+{
+ return (USB_DeActivateRemoteWakeup(hpcd->Instance));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral State functions #####
+ ===============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the PCD handle state.
+ * @param hpcd PCD handle
+ * @retval HAL state
+ */
+PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd)
+{
+ return hpcd->State;
+}
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+ * @brief Set the USB Device high speed test mode.
+ * @param hpcd PCD handle
+ * @param testmode USB Device high speed test mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCD_SetTestMode(const PCD_HandleTypeDef *hpcd, uint8_t testmode)
+{
+ const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ switch (testmode)
+ {
+ case TEST_J:
+ case TEST_K:
+ case TEST_SE0_NAK:
+ case TEST_PACKET:
+ case TEST_FORCE_EN:
+ USBx_DEVICE->DCTL &= ~(0x7UL << 4);
+ USBx_DEVICE->DCTL |= (uint32_t)testmode << 4;
+ break;
+
+ default:
+ break;
+ }
+
+ return HAL_OK;
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @addtogroup PCD_Private_Functions
+ * @{
+ */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+ * @brief Check FIFO for the next packet to be loaded.
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ USB_OTG_EPTypeDef *ep;
+ uint32_t len;
+ uint32_t len32b;
+ uint32_t fifoemptymsk;
+
+ ep = &hpcd->IN_ep[epnum];
+
+ if (ep->xfer_count > ep->xfer_len)
+ {
+ return HAL_ERROR;
+ }
+
+ len = ep->xfer_len - ep->xfer_count;
+
+ if (len > ep->maxpacket)
+ {
+ len = ep->maxpacket;
+ }
+
+ len32b = (len + 3U) / 4U;
+
+ while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
+ (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
+ {
+ /* Write the FIFO */
+ len = ep->xfer_len - ep->xfer_count;
+
+ if (len > ep->maxpacket)
+ {
+ len = ep->maxpacket;
+ }
+ len32b = (len + 3U) / 4U;
+
+ (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len,
+ (uint8_t)hpcd->Init.dma_enable);
+
+ ep->xfer_buff += len;
+ ep->xfer_count += len;
+ }
+
+ if (ep->xfer_len <= ep->xfer_count)
+ {
+ fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
+ USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief process EP OUT transfer complete interrupt.
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+ USB_OTG_EPTypeDef *ep;
+ const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
+ uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
+
+ if (hpcd->Init.dma_enable == 1U)
+ {
+ if ((DoepintReg & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) /* Class C */
+ {
+ /* StupPktRcvd = 1 this is a setup packet */
+ if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
+ ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+ }
+ }
+ else if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) /* Class E */
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
+ }
+ else if ((DoepintReg & (USB_OTG_DOEPINT_STUP | USB_OTG_DOEPINT_OTEPSPR)) == 0U)
+ {
+ /* StupPktRcvd = 1 this is a setup packet */
+ if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
+ ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+ }
+ else
+ {
+ ep = &hpcd->OUT_ep[epnum];
+
+ /* out data packet received over EP */
+ ep->xfer_count = ep->xfer_size - (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
+
+ if (epnum == 0U)
+ {
+ if (ep->xfer_len == 0U)
+ {
+ /* this is ZLP, so prepare EP0 for next setup */
+ (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
+ }
+ else
+ {
+ ep->xfer_buff += ep->xfer_count;
+ }
+ }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
+#else
+ HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ /* ... */
+ }
+ }
+ else
+ {
+ if (gSNPSiD == USB_OTG_CORE_ID_310A)
+ {
+ /* StupPktRcvd = 1 this is a setup packet */
+ if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+ }
+ else
+ {
+ if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
+ }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
+#else
+ HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ }
+ else
+ {
+ if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
+ {
+ /* this is ZLP, so prepare EP0 for next setup */
+ (void)USB_EP0_OutStart(hpcd->Instance, 0U, (uint8_t *)hpcd->Setup);
+ }
+
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
+#else
+ HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief process EP OUT setup packet received interrupt.
+ * @param hpcd PCD handle
+ * @param epnum endpoint number
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
+{
+ const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
+ uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
+
+ if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
+ ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
+ {
+ CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
+ }
+
+ /* Inform the upper layer that a setup packet is available */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->SetupStageCallback(hpcd);
+#else
+ HAL_PCD_SetupStageCallback(hpcd);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+
+ if ((gSNPSiD > USB_OTG_CORE_ID_300A) && (hpcd->Init.dma_enable == 1U))
+ {
+ (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
+ }
+
+ return HAL_OK;
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+ * @}
+ */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* HAL_PCD_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c
new file mode 100755
index 0000000..1d4bfe9
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c
@@ -0,0 +1,341 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_pcd_ex.c
+ * @author MCD Application Team
+ * @brief PCD Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the USB Peripheral Controller:
+ * + Extended features functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PCDEx PCDEx
+ * @brief PCD Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/* 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
+ * @{
+ */
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/**
+ * @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;
+ uint32_t Tx_Offset;
+
+ /* 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 == 0U)
+ {
+ hpcd->Instance->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
+ }
+ else
+ {
+ Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
+ for (i = 0U; i < (fifo - 1U); i++)
+ {
+ Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
+ }
+
+ /* Multiply Tx_Size by 2 to get higher performance */
+ hpcd->Instance->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set Rx FIFO
+ * @param hpcd PCD handle
+ * @param size Size of Rx fifo
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
+{
+ hpcd->Instance->GRXFSIZ = size;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Activate LPM feature.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ hpcd->lpm_active = 1U;
+ hpcd->LPM_State = LPM_L0;
+ USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM;
+ USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate LPM feature.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ hpcd->lpm_active = 0U;
+ USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM;
+ USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Handle BatteryCharging Process.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Enable DCD : Data Contact Detect */
+ USBx->GCCFG |= USB_OTG_GCCFG_DCDEN;
+
+ /* Wait for Min DCD Timeout */
+ HAL_Delay(300U);
+
+ /* Check Detect flag */
+ if ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == USB_OTG_GCCFG_DCDET)
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
+#else
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+
+ /* Primary detection: checks if connected to Standard Downstream Port
+ (without charging capability) */
+ USBx->GCCFG &= ~USB_OTG_GCCFG_DCDEN;
+ HAL_Delay(50U);
+ USBx->GCCFG |= USB_OTG_GCCFG_PDEN;
+ HAL_Delay(50U);
+
+ if ((USBx->GCCFG & USB_OTG_GCCFG_PDET) == 0U)
+ {
+ /* Case of Standard Downstream Port */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
+#else
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* start secondary detection to check connection to Charging Downstream
+ Port or Dedicated Charging Port */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
+ HAL_Delay(50U);
+ USBx->GCCFG |= USB_OTG_GCCFG_SDEN;
+ HAL_Delay(50U);
+
+ if ((USBx->GCCFG & USB_OTG_GCCFG_SDET) == USB_OTG_GCCFG_SDET)
+ {
+ /* case Dedicated Charging Port */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
+#else
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+ /* case Charging Downstream Port */
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
+#else
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ }
+
+ /* Battery Charging capability discovery finished */
+ (void)HAL_PCDEx_DeActivateBCD(hpcd);
+
+ /* Check for the Timeout, else start USB Device */
+ if ((HAL_GetTick() - tickstart) > 1000U)
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
+#else
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+ else
+ {
+#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
+ hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
+#else
+ HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
+#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
+ }
+}
+
+/**
+ * @brief Activate BatteryCharging feature.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
+
+ /* Power Down USB transceiver */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+
+ /* Enable Battery charging */
+ USBx->GCCFG |= USB_OTG_GCCFG_BCDEN;
+
+ hpcd->battery_charging_active = 1U;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Deactivate BatteryCharging feature.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
+{
+ USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
+
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
+
+ /* Disable Battery charging */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
+
+ hpcd->battery_charging_active = 0U;
+
+ return HAL_OK;
+}
+
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+ * @brief Send LPM message to user layer callback.
+ * @param hpcd PCD handle
+ * @param msg LPM message
+ * @retval HAL status
+ */
+__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(msg);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCDEx_LPM_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Send BatteryCharging message to user layer callback.
+ * @param hpcd PCD handle
+ * @param msg LPM message
+ * @retval HAL status
+ */
+__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hpcd);
+ UNUSED(msg);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PCDEx_BCD_Callback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c
new file mode 100755
index 0000000..345a9f5
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr.c
@@ -0,0 +1,876 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_pwr.c
+ * @author MCD Application Team
+ * @brief PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Power Controller (PWR) peripheral:
+ * + Initialization and de-initialization functions.
+ * + Peripheral Control functions.
+ * + Interrupt Handling functions.
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### PWR peripheral overview #####
+ ==============================================================================
+ [..]
+ (#) The Power control (PWR) provides an overview of the supply architecture
+ for the different power domains and of the supply configuration
+ controller.
+ In the H7 family, the number of power domains is different between
+ device lines. This difference is due to characteristics of each device.
+
+ (#) Domain architecture overview for the different H7 lines:
+ (+) Dual core lines are STM32H745, STM32H747, STM32H755 and STM32H757.
+ These devices have 3 power domains (D1, D2 and D3).
+ The domain D1 contains a CPU (Cortex-M7), a Flash memory and some
+ peripherals. The D2 domain contains peripherals and a CPU
+ (Cortex-M4). The D3 domain contains the system control, I/O logic
+ and low-power peripherals.
+ (+) STM32H72x, STM32H73x, STM32H742, STM32H743, STM32H750 and STM32H753
+ devices have 3 power domains (D1, D2 and D3).
+ The domain D1 contains a CPU (Cortex-M7), a Flash memory and some
+ peripherals. The D2 domain contains peripherals. The D3 domains
+ contains the system control, I/O logic and low-power peripherals.
+ (+) STM32H7Axxx and STM32H7Bxxx devices have 2 power domains (CD and SRD).
+ The core domain (CD) contains a CPU (Cortex-M7), a Flash
+ memory and peripherals. The SmartRun domain contains the system
+ control, I/O logic and low-power peripherals.
+
+ (#) Every entity have low power mode as described below :
+ (#) The CPU low power modes are :
+ (+) CPU CRUN.
+ (+) CPU CSLEEP.
+ (+) CPU CSTOP.
+ (#) The domain low power modes are :
+ (+) DRUN.
+ (+) DSTOP.
+ (+) DSTANDBY.
+ (#) The SYSTEM low power modes are :
+ (+) RUN* : The Run* mode is entered after a POR reset and a wakeup from
+ Standby. In Run* mode, the performance is limited and the
+ system supply configuration shall be programmed. The system
+ enters Run mode only when the ACTVOSRDY bit in PWR control
+ status register 1 (PWR_CSR1) is set to 1.
+ (+) RUN.
+ (+) STOP.
+ (+) STANDBY.
+
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Power management peripheral is active by default at startup level in
+ STM32h7xx lines.
+
+ (#) Call HAL_PWR_EnableBkUpAccess() and HAL_PWR_DisableBkUpAccess() functions
+ to enable/disable access to the backup domain (RTC registers, RTC backup
+ data registers and backup SRAM).
+
+ (#) Call HAL_PWR_ConfigPVD() after setting parameters to be configured (event
+ mode and voltage threshold) in order to set up the Power Voltage Detector,
+ then use HAL_PWR_EnablePVD() and HAL_PWR_DisablePVD() functions to start
+ and stop the PVD detection.
+ (+) PVD level could be one of the following values :
+ (++) 1V95
+ (++) 2V1
+ (++) 2V25
+ (++) 2V4
+ (++) 2V55
+ (++) 2V7
+ (++) 2V85
+ (++) External voltage level
+
+ (#) Call HAL_PWR_EnableWakeUpPin() and HAL_PWR_DisableWakeUpPin() functions
+ with the right parameter to configure the wake up pin polarity (Low or
+ High) and to enable and disable it.
+
+ (#) Call HAL_PWR_EnterSLEEPMode() function to enter the current Core in SLEEP
+ mode. Wake-up from SLEEP mode could be following to an event or an
+ interrupt according to low power mode intrinsic request called (__WFI()
+ or __WFE()).
+ Please ensure to clear all CPU pending events by calling
+ HAL_PWREx_ClearPendingEvent() function when trying to enter the Cortex-Mx
+ in SLEEP mode with __WFE() entry.
+
+ (#) Call HAL_PWR_EnterSTOPMode() function to enter the whole system to Stop 0
+ mode for single core devices. For dual core devices, this API will enter
+ the domain (containing Cortex-Mx that executing this function) in DSTOP
+ mode. According to the used parameter, user could select the regulator to
+ be kept actif in low power mode and wake-up event type.
+ Please ensure to clear all CPU pending events by calling
+ HAL_PWREx_ClearPendingEvent() function when trying to enter the Cortex-Mx
+ in CSTOP mode with __WFE() entry.
+
+ (#) Call HAL_PWR_EnterSTANDBYMode() function to enter the whole system in
+ STANDBY mode for single core devices. For dual core devices, this API
+ will enter the domain (containing Cortex-Mx that executing this function)
+ in DSTANDBY mode.
+
+ (#) Call HAL_PWR_EnableSleepOnExit() and HAL_PWR_DisableSleepOnExit() APIs to
+ enable and disable the Cortex-Mx re-entring in SLEEP mode after an
+ interruption handling is over.
+
+ (#) Call HAL_PWR_EnableSEVOnPend() and HAL_PWR_DisableSEVOnPend() functions
+ to configure the Cortex-Mx to wake-up after any pending event / interrupt
+ even if it's disabled or has insufficient priority to cause exception
+ entry.
+
+ (#) Call HAL_PWR_PVD_IRQHandler() function to handle the PWR PVD interrupt
+ request.
+
+ *** PWR HAL driver macros list ***
+ =============================================
+ [..]
+ Below the list of most used macros in PWR HAL driver.
+
+ (+) __HAL_PWR_VOLTAGESCALING_CONFIG() : Configure the main internal
+ regulator output voltage.
+ (+) __HAL_PWR_GET_FLAG() : Get the PWR pending flags.
+ (+) __HAL_PWR_CLEAR_FLAG() : Clear the PWR pending flags.
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PWR PWR
+ * @brief PWR HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @addtogroup PWR_Private_Constants PWR Private Constants
+ * @{
+ */
+
+/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask
+ * @{
+ */
+#if !defined (DUAL_CORE)
+#define PVD_MODE_IT (0x00010000U)
+#define PVD_MODE_EVT (0x00020000U)
+#endif /* !defined (DUAL_CORE) */
+
+#define PVD_RISING_EDGE (0x00000001U)
+#define PVD_FALLING_EDGE (0x00000002U)
+#define PVD_RISING_FALLING_EDGE (0x00000003U)
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* 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 #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to deinitialize power peripheral.
+
+ [..]
+ After system reset, the backup domain (RTC registers, RTC backup data
+ registers and backup SRAM) is protected against possible unwanted write
+ accesses.
+ The HAL_PWR_EnableBkUpAccess() function enables the access to the backup
+ domain.
+ The HAL_PWR_DisableBkUpAccess() function disables the access to the backup
+ domain.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Deinitialize the HAL PWR peripheral registers to their default reset
+ * values.
+ * @note This functionality is not available in this product.
+ * The prototype is kept just to maintain compatibility with other
+ * products.
+ * @retval None.
+ */
+void HAL_PWR_DeInit (void)
+{
+}
+
+/**
+ * @brief Enable 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 Disable 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 Power Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control Functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to control power peripheral.
+
+ *** PVD configuration ***
+ =========================
+ [..]
+ (+) The PVD is used to monitor the VDD power supply by comparing it to a
+ threshold selected by the PVD Level (PLS[7:0] bits in the PWR_CR1
+ register).
+
+ (+) A PVDO flag is available to indicate if VDD is higher or lower
+ than the PVD threshold. This event is internally connected to the EXTI
+ line 16 to generate an interrupt if enabled.
+ It is configurable 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.
+ The pin pull is configurable through the WKUPEPR register to be in
+ No-pull, Pull-up and Pull-down.
+ The pin polarity is configurable through the WKUPEPR register to be
+ active on rising or falling edges.
+
+ (+) There are up to six Wake-up pin in the STM32H7 devices family.
+
+ *** Low Power modes configuration ***
+ =====================================
+ [..]
+ The device present 3 principles low-power modes features:
+ (+) SLEEP mode : Cortex-Mx is stopped and all PWR domains are remaining
+ active (Powered and Clocked).
+
+ (+) STOP mode : Cortex-Mx is stopped, clocks are stopped and the
+ regulator is running. The Main regulator or the LP
+ regulator could be selected.
+
+ (+) STANDBY mode : All PWR domains enter DSTANDBY mode and the VCORE
+ supply regulator is powered off.
+
+ *** SLEEP mode ***
+ ==================
+ [..]
+ (+) Entry:
+ The SLEEP mode is entered by using the HAL_PWR_EnterSLEEPMode(Regulator,
+ SLEEPEntry) function.
+
+ (++) 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 STM32H7 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 system 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(Regulator,
+ STOPEntry) function with:
+
+ (++) Regulator:
+ (+++) PWR_MAINREGULATOR_ON: Main regulator ON.
+ (+++) PWR_LOWPOWERREGULATOR_ON: Low Power regulator ON.
+
+ (++) STOPEntry:
+ (+++) PWR_STOPENTRY_WFI: enter STOP mode with WFI instruction.
+ (+++) PWR_STOPENTRY_WFE: enter STOP mode with WFE instruction.
+
+ (+) Exit:
+ Any EXTI Line (Internal or External) configured in Interrupt/Event mode.
+
+ *** STANDBY mode ***
+ ====================
+ [..]
+ (+)
+ The system STANDBY mode allows to achieve the lowest power consumption.
+ It is based on the Cortex-Mx deep SLEEP mode, with the voltage regulator
+ disabled. The system 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 Configure the event mode and the voltage threshold detected by the
+ * Programmable 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.
+ * @note For dual core devices, please ensure to configure the EXTI lines for
+ * the different Cortex-Mx through PWR_Exported_Macro provided by this
+ * driver. All combination are allowed: wake up only Cortex-M7, wake up
+ * only Cortex-M4 or wake up Cortex-M7 and Cortex-M4.
+ * @retval None.
+ */
+void HAL_PWR_ConfigPVD (const PWR_PVDTypeDef *sConfigPVD)
+{
+ /* Check the PVD configuration parameter */
+ if (sConfigPVD == NULL)
+ {
+ return;
+ }
+
+ /* 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 previous config */
+#if !defined (DUAL_CORE)
+ __HAL_PWR_PVD_EXTI_DISABLE_EVENT ();
+ __HAL_PWR_PVD_EXTI_DISABLE_IT ();
+#endif /* !defined (DUAL_CORE) */
+
+ __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE ();
+ __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE ();
+
+#if !defined (DUAL_CORE)
+ /* Interrupt mode configuration */
+ if ((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_IT ();
+ }
+
+ /* Event mode configuration */
+ if ((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_EVENT ();
+ }
+#endif /* !defined (DUAL_CORE) */
+
+ /* Rising edge configuration */
+ if ((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE ();
+ }
+
+ /* Falling edge configuration */
+ if ((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE)
+ {
+ __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE ();
+ }
+}
+
+/**
+ * @brief Enable the Programmable Voltage Detector (PVD).
+ * @retval None.
+ */
+void HAL_PWR_EnablePVD (void)
+{
+ /* Enable the power voltage detector */
+ SET_BIT (PWR->CR1, PWR_CR1_PVDEN);
+}
+
+/**
+ * @brief Disable the Programmable Voltage Detector (PVD).
+ * @retval None.
+ */
+void HAL_PWR_DisablePVD (void)
+{
+ /* Disable the power voltage detector */
+ CLEAR_BIT (PWR->CR1, PWR_CR1_PVDEN);
+}
+
+/**
+ * @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 (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 values where the user can explicitly states
+ * the enabled pin and the chosen polarity:
+ * @arg PWR_WAKEUP_PIN1_HIGH, PWR_WAKEUP_PIN1_LOW,
+ * PWR_WAKEUP_PIN2_HIGH, PWR_WAKEUP_PIN2_LOW,
+ * PWR_WAKEUP_PIN3_HIGH, PWR_WAKEUP_PIN3_LOW,
+ * PWR_WAKEUP_PIN4_HIGH, PWR_WAKEUP_PIN4_LOW,
+ * PWR_WAKEUP_PIN5_HIGH, PWR_WAKEUP_PIN5_LOW,
+ * PWR_WAKEUP_PIN6_HIGH, PWR_WAKEUP_PIN6_LOW.
+ * @note PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent.
+ * @note The PWR_WAKEUP_PIN3_HIGH, PWR_WAKEUP_PIN3_LOW, PWR_WAKEUP_PIN5_HIGH
+ * and PWR_WAKEUP_PIN5_LOW are available only for devices that includes
+ * GPIOI port.
+ * @retval None.
+ */
+void HAL_PWR_EnableWakeUpPin (uint32_t WakeUpPinPolarity)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_WAKEUP_PIN (WakeUpPinPolarity));
+
+ /*
+ Enable and Specify the Wake-Up pin polarity and the pull configuration
+ for the event detection (rising or falling edge).
+ */
+ MODIFY_REG (PWR->WKUPEPR, PWR_EWUP_MASK, WakeUpPinPolarity);
+}
+
+/**
+ * @brief Disable the WakeUp PINx functionality.
+ * @param WakeUpPinx : Specifies the Power Wake-Up pin to disable.
+ * This parameter can be one of the following values:
+ * @arg PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3,
+ * PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5, PWR_WAKEUP_PIN6,
+ * PWR_WAKEUP_PIN1_HIGH, PWR_WAKEUP_PIN1_LOW,
+ * PWR_WAKEUP_PIN2_HIGH, PWR_WAKEUP_PIN2_LOW,
+ * PWR_WAKEUP_PIN3_HIGH, PWR_WAKEUP_PIN3_LOW,
+ * PWR_WAKEUP_PIN4_HIGH, PWR_WAKEUP_PIN4_LOW,
+ * PWR_WAKEUP_PIN5_HIGH, PWR_WAKEUP_PIN5_LOW,
+ * PWR_WAKEUP_PIN6_HIGH, PWR_WAKEUP_PIN6_LOW.
+ * @note The PWR_WAKEUP_PIN3_HIGH, PWR_WAKEUP_PIN3_LOW, PWR_WAKEUP_PIN5_HIGH
+ * and PWR_WAKEUP_PIN5_LOW are available only for devices that includes
+ * GPIOI port.
+ * @retval None.
+ */
+void HAL_PWR_DisableWakeUpPin (uint32_t WakeUpPinx)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_WAKEUP_PIN (WakeUpPinx));
+
+ /* Disable the wake up pin selected */
+ CLEAR_BIT (PWR->WKUPEPR, (PWR_WKUPEPR_WKUPEN & WakeUpPinx));
+}
+
+/**
+ * @brief Enter the current core in SLEEP mode (CSLEEP).
+ * @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 STM32H7 family and is kept as
+ * parameter just to maintain compatibility with the lower power
+ * families.
+ * @param SLEEPEntry : Specifies if SLEEP mode is entered with WFI or WFE
+ * intrinsic 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.
+ * @note Ensure to clear pending events before calling this API through
+ * HAL_PWREx_ClearPendingEvent() when the SLEEP entry is WFE.
+ * @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));
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Regulator);
+
+ /* Clear SLEEPDEEP bit of Cortex System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* Select SLEEP mode entry */
+ if (SLEEPEntry == PWR_SLEEPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI ();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __WFE ();
+ }
+}
+
+/**
+ * @brief Enter STOP mode.
+ * @note For single core devices, this API will enter the system in STOP mode
+ * with all domains in DSTOP, if RUN_D3/RUN_SRD bit in CPUCR register is
+ * cleared.
+ * For dual core devices, this API will enter the domain (containing
+ * Cortex-Mx that executing this function) in DSTOP mode. If all
+ * Cortex-Mx domains are in DSTOP and RUN_D3 bit in CPUCR register is
+ * cleared, all the system will enter in STOP mode.
+ * @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
+ * intrinsic 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.
+ * @note In System STOP mode, all I/O pins keep the same state as in Run mode.
+ * @note When exiting System STOP mode by issuing an interrupt or a wakeup
+ * event, the HSI RC oscillator is selected as default system wakeup
+ * clock.
+ * @note In System STOP mode, when the voltage regulator operates in low
+ * power mode, an additional startup delay is incurred when the system
+ * is waking up. By keeping the internal regulator ON during STOP mode,
+ * the consumption is higher although the startup time is reduced.
+ * @retval None.
+ */
+void HAL_PWR_EnterSTOPMode (uint32_t Regulator, uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_REGULATOR (Regulator));
+ assert_param (IS_PWR_STOP_ENTRY (STOPEntry));
+
+ /* Select the regulator state in STOP mode */
+ MODIFY_REG (PWR->CR1, PWR_CR1_LPDS, Regulator);
+
+ /* Configure the PWR mode for the different Domains */
+#if defined (DUAL_CORE)
+ /* Check CPU ID */
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+ {
+ /* Keep DSTOP mode when Cortex-M7 enters DEEP-SLEEP */
+ CLEAR_BIT (PWR->CPUCR, (PWR_CPUCR_PDDS_D1 | PWR_CPUCR_PDDS_D3));
+ }
+ else
+ {
+ /* Keep DSTOP mode when Cortex-M4 enters DEEP-SLEEP */
+ CLEAR_BIT (PWR->CPUCR, (PWR_CPUCR_PDDS_D2 | PWR_CPUCR_PDDS_D3));
+ }
+#else /* Single core devices */
+ /* Keep DSTOP mode when Cortex-M7 enter in DEEP-SLEEP */
+ CLEAR_BIT (PWR->CPUCR, (PWR_CPUCR_PDDS_D1 | PWR_CPUCR_PDDS_D3));
+
+#if defined (PWR_CPUCR_PDDS_D2)
+ /* Keep DSTOP mode when Cortex-M7 enter in DEEP-SLEEP */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D2);
+#endif /* PWR_CPUCR_PDDS_D2 */
+#endif /* defined (DUAL_CORE) */
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* Ensure that all instructions are done before entering STOP mode */
+ __DSB ();
+ __ISB ();
+
+ /* Select STOP mode entry */
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI ();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __WFE ();
+ }
+
+ /* Clear SLEEPDEEP bit of Cortex-Mx in the System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+}
+
+/**
+ * @brief Enter STANDBY mode.
+ * @note For single core devices, this API will enter the system in STANDBY
+ * mode with all domains in DSTANDBY, if RUN_D3/RUN_SRD bit in CPUCR
+ * register is cleared.
+ * For dual core devices, this API will enter the domain (containing
+ * Cortex-Mx that executing this function) in DSTANDBY mode. If all
+ * Cortex-Mx domains are in DSTANDBY and RUN_D3 bit in CPUCR register
+ * is cleared, all the system will enter in STANDBY mode.
+ * @note The system enters Standby mode only when all domains are in DSTANDBY.
+ * @note When the System exit STANDBY mode by issuing an interrupt or a
+ * wakeup event, the HSI RC oscillator is selected as system clock.
+ * @note It is recommended to disable all regulators before entring STANDBY
+ * mode for power consumption saving purpose.
+ * @retval None.
+ */
+void HAL_PWR_EnterSTANDBYMode (void)
+{
+ /* Configure the PWR mode for the different Domains */
+#if defined (DUAL_CORE)
+ /* Check CPU ID */
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+ {
+ /* Enter DSTANDBY mode when Cortex-M7 enters DEEP-SLEEP */
+ SET_BIT (PWR->CPUCR, (PWR_CPUCR_PDDS_D1 | PWR_CPUCR_PDDS_D3));
+ SET_BIT (PWR->CPU2CR, (PWR_CPU2CR_PDDS_D1 | PWR_CPU2CR_PDDS_D3));
+ }
+ else
+ {
+ /* Enter DSTANDBY mode when Cortex-M4 enters DEEP-SLEEP */
+ SET_BIT (PWR->CPUCR, (PWR_CPUCR_PDDS_D2 | PWR_CPUCR_PDDS_D3));
+ SET_BIT (PWR->CPU2CR, (PWR_CPU2CR_PDDS_D2 | PWR_CPU2CR_PDDS_D3));
+ }
+#else /* Single core devices */
+ /* Enter DSTANDBY mode when Cortex-M7 enters DEEP-SLEEP */
+ SET_BIT (PWR->CPUCR, (PWR_CPUCR_PDDS_D1 | PWR_CPUCR_PDDS_D3));
+
+#if defined (PWR_CPUCR_PDDS_D2)
+ /* Enter DSTANDBY mode when Cortex-M7 enters DEEP-SLEEP */
+ SET_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D2);
+#endif /* PWR_CPUCR_PDDS_D2 */
+#endif /* defined (DUAL_CORE) */
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* Ensure that all instructions are done before entering STOP mode */
+ __DSB ();
+ __ISB ();
+
+ /* This option is used to ensure that store operations are completed */
+#if defined (__CC_ARM)
+ __force_stores();
+#endif /* defined (__CC_ARM) */
+
+ /* Request Wait For Interrupt */
+ __WFI ();
+}
+
+/**
+ * @brief Indicate Sleep-On-Exit feature 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-Mx System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPONEXIT_Msk);
+}
+
+/**
+ * @brief Disable 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-Mx System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SLEEPONEXIT_Msk);
+}
+
+/**
+ * @brief Enable CORTEX SEVONPEND feature.
+ * @note Sets SEVONPEND bit of SCR register. When this bit is set, any
+ * pending event / interrupt even if it's disabled or has insufficient
+ * priority to cause exception entry wakes up the Cortex-Mx.
+ * @retval None.
+ */
+void HAL_PWR_EnableSEVOnPend (void)
+{
+ /* Set SEVONPEND bit of Cortex-Mx System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SEVONPEND_Msk);
+}
+
+/**
+ * @brief Disable CORTEX SEVONPEND feature.
+ * @note Resets SEVONPEND bit of SCR register. When this bit is reset, only
+ * enabled pending causes exception entry wakes up the Cortex-Mx.
+ * @retval None.
+ */
+void HAL_PWR_DisableSEVOnPend (void)
+{
+ /* Clear SEVONPEND bit of Cortex System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SEVONPEND_Msk);
+}
+/**
+ * @}
+ */
+
+/** @defgroup PWR_Exported_Functions_Group3 Interrupt Handling Functions
+ * @brief Interrupt Handling functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Interrupt Handling Functions #####
+ ===============================================================================
+ [..]
+ This section provides functions allowing to handle the PVD pending
+ interrupts.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief This function handles the PWR PVD interrupt request.
+ * @note This API should be called under the PVD_AVD_IRQHandler().
+ * @retval None.
+ */
+void HAL_PWR_PVD_IRQHandler (void)
+{
+#if defined (DUAL_CORE)
+ /* Check Cortex-Mx ID */
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+ {
+ /* Check PWR EXTI D1 flag */
+ if(__HAL_PWR_PVD_EXTI_GET_FLAG () != 0U)
+ {
+ /* Clear PWR EXTI D1 pending bit */
+ __HAL_PWR_PVD_EXTI_CLEAR_FLAG ();
+
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback ();
+ }
+ }
+ else
+ {
+ /* Check PWR EXTI D2 flag */
+ if (__HAL_PWR_PVD_EXTID2_GET_FLAG () != 0U)
+ {
+ /* Clear PWR EXTI D2 pending bit */
+ __HAL_PWR_PVD_EXTID2_CLEAR_FLAG ();
+
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback ();
+ }
+ }
+#else /* Single core devices */
+ /* PVD EXTI line interrupt detected */
+ if (__HAL_PWR_PVD_EXTI_GET_FLAG () != 0U)
+ {
+ /* Clear PWR EXTI pending bit */
+ __HAL_PWR_PVD_EXTI_CLEAR_FLAG ();
+
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback ();
+ }
+#endif /* defined (DUAL_CORE) */
+}
+
+/**
+ * @brief PWR PVD interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWR_PVDCallback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWR_PVDCallback can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c
new file mode 100755
index 0000000..6faff73
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pwr_ex.c
@@ -0,0 +1,2158 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_pwr_ex.c
+ * @author MCD Application Team
+ * @brief Extended PWR HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of PWR extension peripheral:
+ * + Peripheral Extended features functions
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Call HAL_PWREx_ConfigSupply() function to configure the regulator supply
+ with the following different setups according to hardware (support SMPS):
+ (+) PWR_DIRECT_SMPS_SUPPLY
+ (+) PWR_SMPS_1V8_SUPPLIES_LDO
+ (+) PWR_SMPS_2V5_SUPPLIES_LDO
+ (+) PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO
+ (+) PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO
+ (+) PWR_SMPS_1V8_SUPPLIES_EXT
+ (+) PWR_SMPS_2V5_SUPPLIES_EXT
+ (+) PWR_LDO_SUPPLY
+ (+) PWR_EXTERNAL_SOURCE_SUPPLY
+
+ (#) Call HAL_PWREx_GetSupplyConfig() function to get the current supply setup.
+
+ (#) Call HAL_PWREx_ControlVoltageScaling() function to configure the main
+ internal regulator output voltage. The voltage scaling could be one of
+ the following scales :
+ (+) PWR_REGULATOR_VOLTAGE_SCALE0
+ (+) PWR_REGULATOR_VOLTAGE_SCALE1
+ (+) PWR_REGULATOR_VOLTAGE_SCALE2
+ (+) PWR_REGULATOR_VOLTAGE_SCALE3
+
+ (#) Call HAL_PWREx_GetVoltageRange() function to get the current output
+ voltage applied to the main regulator.
+
+ (#) Call HAL_PWREx_ControlStopModeVoltageScaling() function to configure the
+ main internal regulator output voltage in STOP mode. The voltage scaling
+ in STOP mode could be one of the following scales :
+ (+) PWR_REGULATOR_SVOS_SCALE3
+ (+) PWR_REGULATOR_SVOS_SCALE4
+ (+) PWR_REGULATOR_SVOS_SCALE5
+
+ (#) Call HAL_PWREx_GetStopModeVoltageRange() function to get the current
+ output voltage applied to the main regulator in STOP mode.
+
+ (#) Call HAL_PWREx_EnterSTOP2Mode() function to enter the system in STOP mode
+ with core domain in D2STOP mode. This API is used only for STM32H7Axxx
+ and STM32H7Bxxx devices.
+ Please ensure to clear all CPU pending events by calling
+ HAL_PWREx_ClearPendingEvent() function when trying to enter the Cortex-Mx
+ in DEEP-SLEEP mode with __WFE() entry.
+
+ (#) Call HAL_PWREx_EnterSTOPMode() function to enter the selected domain in
+ DSTOP mode. Call this API with all available power domains to enter the
+ system in STOP mode.
+ Please ensure to clear all CPU pending events by calling
+ HAL_PWREx_ClearPendingEvent() function when trying to enter the Cortex-Mx
+ in DEEP-SLEEP mode with __WFE() entry.
+
+ (#) Call HAL_PWREx_ClearPendingEvent() function always before entring the
+ Cortex-Mx in any low power mode (SLEEP/DEEP-SLEEP) using WFE entry.
+
+ (#) Call HAL_PWREx_EnterSTANDBYMode() function to enter the selected domain
+ in DSTANDBY mode. Call this API with all available power domains to enter
+ the system in STANDBY mode.
+
+ (#) Call HAL_PWREx_ConfigD3Domain() function to setup the D3/SRD domain state
+ (RUN/STOP) when the system enter to low power mode.
+
+ (#) Call HAL_PWREx_ClearDomainFlags() function to clear the CPU flags for the
+ selected power domain. This API is used only for dual core devices.
+
+ (#) Call HAL_PWREx_HoldCore() and HAL_PWREx_ReleaseCore() functions to hold
+ and release the selected CPU and and their domain peripherals when
+ exiting STOP mode. These APIs are used only for dual core devices.
+
+ (#) Call HAL_PWREx_EnableFlashPowerDown() and
+ HAL_PWREx_DisableFlashPowerDown() functions to enable and disable the
+ Flash Power Down in STOP mode.
+
+ (#) Call HAL_PWREx_EnableMemoryShutOff() and
+ HAL_PWREx_DisableMemoryShutOff() functions to enable and disable the
+ memory block shut-off in DStop or DStop2. These APIs are used only for
+ STM32H7Axxx and STM32H7Bxxx lines.
+
+ (#) Call HAL_PWREx_EnableWakeUpPin() and HAL_PWREx_DisableWakeUpPin()
+ functions to enable and disable the Wake-up pin functionality for
+ the selected pin.
+
+ (#) Call HAL_PWREx_GetWakeupFlag() and HAL_PWREx_ClearWakeupFlag()
+ functions to manage wake-up flag for the selected pin.
+
+ (#) Call HAL_PWREx_WAKEUP_PIN_IRQHandler() function to handle all wake-up
+ pins interrupts.
+
+ (#) Call HAL_PWREx_EnableBkUpReg() and HAL_PWREx_DisableBkUpReg() functions
+ to enable and disable the backup domain regulator.
+
+ (#) Call HAL_PWREx_EnableUSBReg(), HAL_PWREx_DisableUSBReg(),
+ HAL_PWREx_EnableUSBVoltageDetector() and
+ HAL_PWREx_DisableUSBVoltageDetector() functions to manage USB power
+ regulation functionalities.
+
+ (#) Call HAL_PWREx_EnableBatteryCharging() and
+ HAL_PWREx_DisableBatteryCharging() functions to enable and disable the
+ battery charging feature with the selected resistor.
+
+ (#) Call HAL_PWREx_EnableAnalogBooster() and
+ HAL_PWREx_DisableAnalogBooster() functions to enable and disable the
+ AVD boost feature when the VDD supply voltage is below 2V7.
+
+ (#) Call HAL_PWREx_EnableMonitoring() and HAL_PWREx_DisableMonitoring()
+ functions to enable and disable the VBAT and Temperature monitoring.
+ When VBAT and Temperature monitoring feature is enables, use
+ HAL_PWREx_GetTemperatureLevel() and HAL_PWREx_GetVBATLevel() to get
+ respectively the Temperature level and VBAT level.
+
+ (#) Call HAL_PWREx_GetMMCVoltage() and HAL_PWREx_DisableMonitoring()
+ function to get VDDMMC voltage level. This API is used only for
+ STM32H7Axxx and STM32H7Bxxx lines
+
+ (#) Call HAL_PWREx_ConfigAVD() after setting parameter to be configured
+ (event mode and voltage threshold) in order to set up the Analog Voltage
+ Detector then use HAL_PWREx_EnableAVD() and HAL_PWREx_DisableAVD()
+ functions to start and stop the AVD detection.
+ (+) AVD level could be one of the following values :
+ (++) 1V7
+ (++) 2V1
+ (++) 2V5
+ (++) 2V8
+
+ (#) Call HAL_PWREx_PVD_AVD_IRQHandler() function to handle the PWR PVD and
+ AVD interrupt request.
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup PWREx PWREx
+ * @brief PWR Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_PWR_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @addtogroup PWREx_Private_Constants
+ * @{
+ */
+
+/** @defgroup PWREx_AVD_Mode_Mask PWR Extended AVD Mode Mask
+ * @{
+ */
+#define AVD_MODE_IT (0x00010000U)
+#define AVD_MODE_EVT (0x00020000U)
+#define AVD_RISING_EDGE (0x00000001U)
+#define AVD_FALLING_EDGE (0x00000002U)
+#define AVD_RISING_FALLING_EDGE (0x00000003U)
+/**
+ * @}
+ */
+
+/** @defgroup PWREx_REG_SET_TIMEOUT PWR Extended Flag Setting Time Out Value
+ * @{
+ */
+#define PWR_FLAG_SETTING_DELAY (1000U)
+/**
+ * @}
+ */
+
+/** @defgroup PWREx_WakeUp_Pins_Offsets PWREx Wake-Up Pins masks and offsets
+ * @{
+ */
+/* Wake-Up Pins EXTI register mask */
+#if defined (EXTI_IMR2_IM57)
+#define PWR_EXTI_WAKEUP_PINS_MASK (EXTI_IMR2_IM55 | EXTI_IMR2_IM56 |\
+ EXTI_IMR2_IM57 | EXTI_IMR2_IM58 |\
+ EXTI_IMR2_IM59 | EXTI_IMR2_IM60)
+#else
+#define PWR_EXTI_WAKEUP_PINS_MASK (EXTI_IMR2_IM55 | EXTI_IMR2_IM56 |\
+ EXTI_IMR2_IM58 | EXTI_IMR2_IM60)
+#endif /* defined (EXTI_IMR2_IM57) */
+
+/* Wake-Up Pins PWR Pin Pull shift offsets */
+#define PWR_WAKEUP_PINS_PULL_SHIFT_OFFSET (2U)
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup PWREx_Exported_Functions PWREx Exported Functions
+ * @{
+ */
+
+/** @defgroup PWREx_Exported_Functions_Group1 Power Supply Control Functions
+ * @brief Power supply control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Power supply control functions #####
+ ===============================================================================
+ [..]
+ (#) When the system is powered on, the POR monitors VDD supply. Once VDD is
+ above the POR threshold level, the voltage regulator is enabled in the
+ default supply configuration:
+ (+) The Voltage converter output level is set at 1V0 in accordance with
+ the VOS3 level configured in PWR (D3/SRD) domain control register
+ (PWR_D3CR/PWR_SRDCR).
+ (+) The system is kept in reset mode as long as VCORE is not ok.
+ (+) Once VCORE is ok, the system is taken out of reset and the HSI
+ oscillator is enabled.
+ (+) Once the oscillator is stable, the system is initialized: Flash memory
+ and option bytes are loaded and the CPU starts in Run* mode.
+ (+) The software shall then initialize the system including supply
+ configuration programming using the HAL_PWREx_ConfigSupply().
+ (+) Once the supply configuration has been configured, the
+ HAL_PWREx_ConfigSupply() function checks the ACTVOSRDY bit in PWR
+ control status register 1 (PWR_CSR1) to guarantee a valid voltage
+ levels:
+ (++) As long as ACTVOSRDY indicates that voltage levels are invalid, the
+ system is in limited Run* mode, write accesses to the RAMs are not
+ permitted and VOS shall not be changed.
+ (++) Once ACTVOSRDY indicates that voltage levels are valid, the system
+ is in normal Run mode, write accesses to RAMs are allowed and VOS
+ can be changed.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the system Power Supply.
+ * @param SupplySource : Specifies the Power Supply source to set after a
+ * system startup.
+ * This parameter can be one of the following values :
+ * @arg PWR_DIRECT_SMPS_SUPPLY : The SMPS supplies the Vcore Power
+ * Domains. The LDO is Bypassed.
+ * @arg PWR_SMPS_1V8_SUPPLIES_LDO : The SMPS 1.8V output supplies
+ * the LDO. The Vcore Power Domains
+ * are supplied from the LDO.
+ * @arg PWR_SMPS_2V5_SUPPLIES_LDO : The SMPS 2.5V output supplies
+ * the LDO. The Vcore Power Domains
+ * are supplied from the LDO.
+ * @arg PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO : The SMPS 1.8V output
+ * supplies external
+ * circuits and the LDO.
+ * The Vcore Power Domains
+ * are supplied from the
+ * LDO.
+ * @arg PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO : The SMPS 2.5V output
+ * supplies external
+ * circuits and the LDO.
+ * The Vcore Power Domains
+ * are supplied from the
+ * LDO.
+ * @arg PWR_SMPS_1V8_SUPPLIES_EXT : The SMPS 1.8V output supplies
+ * external circuits. The LDO is
+ * Bypassed. The Vcore Power
+ * Domains are supplied from
+ * external source.
+ * @arg PWR_SMPS_2V5_SUPPLIES_EXT : The SMPS 2.5V output supplies
+ * external circuits. The LDO is
+ * Bypassed. The Vcore Power
+ * Domains are supplied from
+ * external source.
+ * @arg PWR_LDO_SUPPLY : The LDO regulator supplies the Vcore Power
+ * Domains. The SMPS regulator is Bypassed.
+ * @arg PWR_EXTERNAL_SOURCE_SUPPLY : The SMPS and the LDO are
+ * Bypassed. The Vcore Power
+ * Domains are supplied from
+ * external source.
+ * @note The PWR_LDO_SUPPLY and PWR_EXTERNAL_SOURCE_SUPPLY are used by all
+ * H7 lines.
+ * The PWR_DIRECT_SMPS_SUPPLY, PWR_SMPS_1V8_SUPPLIES_LDO,
+ * PWR_SMPS_2V5_SUPPLIES_LDO, PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO,
+ * PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO, PWR_SMPS_1V8_SUPPLIES_EXT and
+ * PWR_SMPS_2V5_SUPPLIES_EXT are used only for lines that supports SMPS
+ * regulator.
+ * @note This API is deprecated and is kept only for backward compatibility's sake.
+ * The power supply configuration is handled as part of the system initialization
+ * process during startup.
+ * For more details, please refer to the power control chapter in the reference manual
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_ConfigSupply (uint32_t SupplySource)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param (IS_PWR_SUPPLY (SupplySource));
+
+ /* Check if supply source was configured */
+#if defined (PWR_FLAG_SCUEN)
+ if (__HAL_PWR_GET_FLAG (PWR_FLAG_SCUEN) == 0U)
+#else
+ if ((PWR->CR3 & (PWR_CR3_SMPSEN | PWR_CR3_LDOEN | PWR_CR3_BYPASS)) != (PWR_CR3_SMPSEN | PWR_CR3_LDOEN))
+#endif /* defined (PWR_FLAG_SCUEN) */
+ {
+ /* Check supply configuration */
+ if ((PWR->CR3 & PWR_SUPPLY_CONFIG_MASK) != SupplySource)
+ {
+ /* Supply configuration update locked, can't apply a new supply config */
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Supply configuration update locked, but new supply configuration
+ matches with old supply configuration : nothing to do
+ */
+ return HAL_OK;
+ }
+ }
+
+ /* Set the power supply configuration */
+ MODIFY_REG (PWR->CR3, PWR_SUPPLY_CONFIG_MASK, SupplySource);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till voltage level flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_ACTVOSRDY) == 0U)
+ {
+ if ((HAL_GetTick () - tickstart) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+#if defined (SMPS)
+ /* When the SMPS supplies external circuits verify that SDEXTRDY flag is set */
+ if ((SupplySource == PWR_SMPS_1V8_SUPPLIES_EXT_AND_LDO) ||
+ (SupplySource == PWR_SMPS_2V5_SUPPLIES_EXT_AND_LDO) ||
+ (SupplySource == PWR_SMPS_1V8_SUPPLIES_EXT) ||
+ (SupplySource == PWR_SMPS_2V5_SUPPLIES_EXT))
+ {
+ /* Get the current tick number */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till SMPS external supply ready flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_SMPSEXTRDY) == 0U)
+ {
+ if ((HAL_GetTick () - tickstart) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+ }
+#endif /* defined (SMPS) */
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the power supply configuration.
+ * @retval The supply configuration.
+ */
+uint32_t HAL_PWREx_GetSupplyConfig (void)
+{
+ return (PWR->CR3 & PWR_SUPPLY_CONFIG_MASK);
+}
+
+/**
+ * @brief Configure the main internal regulator output voltage.
+ * @param VoltageScaling : Specifies the regulator output voltage to achieve
+ * a tradeoff between performance and power
+ * consumption.
+ * This parameter can be one of the following values :
+ * @arg PWR_REGULATOR_VOLTAGE_SCALE0 : Regulator voltage output
+ * Scale 0 mode.
+ * @arg PWR_REGULATOR_VOLTAGE_SCALE1 : Regulator voltage output
+ * range 1 mode.
+ * @arg PWR_REGULATOR_VOLTAGE_SCALE2 : Regulator voltage output
+ * range 2 mode.
+ * @arg PWR_REGULATOR_VOLTAGE_SCALE3 : Regulator voltage output
+ * range 3 mode.
+ * @note For STM32H74x and STM32H75x lines, configuring Voltage Scale 0 is
+ * only possible when Vcore is supplied from LDO (Low DropOut). The
+ * SYSCFG Clock must be enabled through __HAL_RCC_SYSCFG_CLK_ENABLE()
+ * macro before configuring Voltage Scale 0.
+ * To enter low power mode , and if current regulator voltage is
+ * Voltage Scale 0 then first switch to Voltage Scale 1 before entering
+ * low power mode.
+ * @retval HAL Status
+ */
+HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling (uint32_t VoltageScaling)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param (IS_PWR_REGULATOR_VOLTAGE (VoltageScaling));
+
+ /* Get the voltage scaling */
+ if ((PWR->CSR1 & PWR_CSR1_ACTVOS) == VoltageScaling)
+ {
+ /* Old and new voltage scaling configuration match : nothing to do */
+ return HAL_OK;
+ }
+
+#if defined (PWR_SRDCR_VOS)
+ /* Set the voltage range */
+ MODIFY_REG (PWR->SRDCR, PWR_SRDCR_VOS, VoltageScaling);
+#else
+#if defined(SYSCFG_PWRCR_ODEN) /* STM32H74xxx and STM32H75xxx lines */
+ if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE0)
+ {
+ if ((PWR->CR3 & PWR_CR3_LDOEN) == PWR_CR3_LDOEN)
+ {
+ /* Set the voltage range */
+ MODIFY_REG (PWR->D3CR, PWR_D3CR_VOS, PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till voltage level flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_ACTVOSRDY) == 0U)
+ {
+ if ((HAL_GetTick () - tickstart) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /* Enable the PWR overdrive */
+ SET_BIT (SYSCFG->PWRCR, SYSCFG_PWRCR_ODEN);
+ }
+ else
+ {
+ /* The voltage scale 0 is only possible when LDO regulator is enabled */
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ if ((PWR->CSR1 & PWR_CSR1_ACTVOS) == PWR_REGULATOR_VOLTAGE_SCALE1)
+ {
+ if ((SYSCFG->PWRCR & SYSCFG_PWRCR_ODEN) != 0U)
+ {
+ /* Disable the PWR overdrive */
+ CLEAR_BIT(SYSCFG->PWRCR, SYSCFG_PWRCR_ODEN);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till voltage level flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_ACTVOSRDY) == 0U)
+ {
+ if ((HAL_GetTick () - tickstart) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+ }
+ }
+
+ /* Set the voltage range */
+ MODIFY_REG (PWR->D3CR, PWR_D3CR_VOS, VoltageScaling);
+ }
+#else /* STM32H72xxx and STM32H73xxx lines */
+ /* Set the voltage range */
+ MODIFY_REG(PWR->D3CR, PWR_D3CR_VOS, VoltageScaling);
+#endif /* defined (SYSCFG_PWRCR_ODEN) */
+#endif /* defined (PWR_SRDCR_VOS) */
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till voltage level flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_ACTVOSRDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the main internal regulator output voltage. Reflecting the last
+ * VOS value applied to the PMU.
+ * @retval The current applied VOS selection.
+ */
+uint32_t HAL_PWREx_GetVoltageRange (void)
+{
+ /* Get the active voltage scaling */
+ return (PWR->CSR1 & PWR_CSR1_ACTVOS);
+}
+
+/**
+ * @brief Configure the main internal regulator output voltage in STOP mode.
+ * @param VoltageScaling : Specifies the regulator output voltage when the
+ * system enters Stop mode to achieve a tradeoff between performance
+ * and power consumption.
+ * This parameter can be one of the following values:
+ * @arg PWR_REGULATOR_SVOS_SCALE3 : Regulator voltage output range
+ * 3 mode.
+ * @arg PWR_REGULATOR_SVOS_SCALE4 : Regulator voltage output range
+ * 4 mode.
+ * @arg PWR_REGULATOR_SVOS_SCALE5 : Regulator voltage output range
+ * 5 mode.
+ * @note The Stop mode voltage scaling for SVOS4 and SVOS5 sets the voltage
+ * regulator in Low-power (LP) mode to further reduce power consumption.
+ * When preselecting SVOS3, the use of the voltage regulator low-power
+ * mode (LP) can be selected by LPDS register bit.
+ * @note The selected SVOS4 and SVOS5 levels add an additional startup delay
+ * when exiting from system Stop mode.
+ * @retval HAL Status.
+ */
+HAL_StatusTypeDef HAL_PWREx_ControlStopModeVoltageScaling (uint32_t VoltageScaling)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_STOP_MODE_REGULATOR_VOLTAGE (VoltageScaling));
+
+ /* Return the stop mode voltage range */
+ MODIFY_REG (PWR->CR1, PWR_CR1_SVOS, VoltageScaling);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Get the main internal regulator output voltage in STOP mode.
+ * @retval The actual applied VOS selection.
+ */
+uint32_t HAL_PWREx_GetStopModeVoltageRange (void)
+{
+ /* Return the stop voltage scaling */
+ return (PWR->CR1 & PWR_CR1_SVOS);
+}
+/**
+ * @}
+ */
+
+/** @defgroup PWREx_Exported_Functions_Group2 Low Power Control Functions
+ * @brief Low power control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Low power control functions #####
+ ===============================================================================
+
+ *** Domains Low Power modes configuration ***
+ =============================================
+ [..]
+ This section provides the extended low power mode control APIs.
+ The system presents 3 principles domains (D1, D2 and D3) that can be
+ operated in low-power modes (DSTOP or DSTANDBY mode):
+
+ (+) DSTOP mode to enters a domain to STOP mode:
+ (++) D1 domain and/or D2 domain enters DSTOP mode only when the CPU
+ subsystem is in CSTOP mode and has allocated peripheral in the
+ domain.
+ In DSTOP mode the domain bus matrix clock is stopped.
+ (++) The system enters STOP mode using one of the following scenarios:
+ (+++) D1 domain enters DSTANDBY mode (powered off) and D2, D3 domains
+ enter DSTOP mode.
+ (+++) D2 domain enters DSTANDBY mode (powered off) and D1, D3 domains
+ enter DSTOP mode.
+ (+++) D3 domain enters DSTANDBY mode (powered off) and D1, D2 domains
+ enter DSTOP mode.
+ (+++) D1 and D2 domains enter DSTANDBY mode (powered off) and D3 domain
+ enters DSTOP mode.
+ (+++) D1 and D3 domains enter DSTANDBY mode (powered off) and D2 domain
+ enters DSTOP mode.
+ (+++) D2 and D3 domains enter DSTANDBY mode (powered off) and D1 domain
+ enters DSTOP mode.
+ (+++) D1, D2 and D3 domains enter DSTOP mode.
+ (++) When the system enters STOP mode, the clocks are stopped and the
+ regulator is running in main or low power mode.
+ (++) D3 domain can be kept in Run mode regardless of the CPU status when
+ enter STOP mode by using HAL_PWREx_ConfigD3Domain(D3State) function.
+
+ (+) DSTANDBY mode to enters a domain to STANDBY mode:
+ (++) The DSTANDBY mode is entered when the PDDS_Dn bit in PWR CPU control
+ register (PWR_CPUCR) for the Dn domain selects Standby mode.
+ (++) The system enters STANDBY mode only when D1, D2 and D3 domains enter
+ DSTANDBY mode. Consequently the VCORE supply regulator is powered
+ off.
+
+ *** DSTOP mode ***
+ ==================
+ [..]
+ In DStop mode the domain bus matrix clock is stopped.
+ The Flash memory can enter low-power Stop mode when it is enabled through
+ FLPS in PWR_CR1 register. This allows a trade-off between domain DStop
+ restart time and low power consumption.
+ [..]
+ In DStop mode domain peripherals using the LSI or LSE clock and
+ peripherals having a kernel clock request are still able to operate.
+ [..]
+ Before entering DSTOP mode it is recommended to call SCB_CleanDCache
+ function in order to clean the D-Cache and guarantee the data integrity
+ for the SRAM memories.
+
+ (+) Entry:
+ The DSTOP mode is entered using the HAL_PWREx_EnterSTOPMode(Regulator,
+ STOPEntry, Domain) function with:
+ (++) Regulator:
+ (+++) PWR_MAINREGULATOR_ON : Main regulator ON.
+ (+++) PWR_LOWPOWERREGULATOR_ON : Low Power regulator ON.
+ (++) STOPEntry:
+ (+++) PWR_STOPENTRY_WFI : enter STOP mode with WFI instruction
+ (+++) PWR_STOPENTRY_WFE : enter STOP mode with WFE instruction
+ (++) Domain:
+ (+++) PWR_D1_DOMAIN : Enters D1/CD domain to DSTOP mode.
+ (+++) PWR_D2_DOMAIN : Enters D2 domain to DSTOP mode.
+ (+++) PWR_D3_DOMAIN : Enters D3/SRD domain to DSTOP mode.
+
+ (+) Exit:
+ Any EXTI Line (Internal or External) configured in Interrupt/Event mode.
+
+ *** DSTANDBY mode ***
+ =====================
+ [..]
+ In DStandby mode:
+ (+) The domain bus matrix clock is stopped.
+ (+) The domain is powered down and the domain RAM and register contents
+ are lost.
+ [..]
+ Before entering DSTANDBY mode it is recommended to call SCB_CleanDCache
+ function in order to clean the D-Cache and guarantee the data integrity
+ for the SRAM memories.
+
+ (+) Entry:
+ The DSTANDBY mode is entered using the HAL_PWREx_EnterSTANDBYMode
+ (Domain) function with:
+ (++) Domain:
+ (+++) PWR_D1_DOMAIN : Enters D1/CD domain to DSTANDBY mode.
+ (+++) PWR_D2_DOMAIN : Enters D2 domain to DSTANDBY mode.
+ (+++) PWR_D3_DOMAIN : Enters D3/SRD domain to DSTANDBY mode.
+
+ (+) 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.
+
+ *** Keep D3/SRD in RUN mode ***
+ ===============================
+ [..]
+ D3/SRD domain can be kept in Run mode regardless of the CPU status when
+ entering STOP mode by using HAL_PWREx_ConfigD3Domain(D3State) function
+ with :
+ (+) D3State:
+ (++) PWR_D3_DOMAIN_STOP : D3/SDR domain follows the CPU sub-system
+ mode.
+ (++) PWR_D3_DOMAIN_RUN : D3/SRD domain remains in Run mode regardless
+ of CPU subsystem mode.
+
+ *** FLASH Power Down configuration ****
+ =======================================
+ [..]
+ By setting the FLPS bit in the PWR_CR1 register 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.
+
+ *** Wakeup Pins configuration ****
+ ===================================
+ [..]
+ Wakeup pins allow the system to exit from Standby mode. The configuration
+ of wakeup pins is done with the HAL_PWREx_EnableWakeUpPin(sPinParams)
+ function with:
+ (+) sPinParams: structure to enable and configure a wakeup pin:
+ (++) WakeUpPin: Wakeup pin to be enabled.
+ (++) PinPolarity: Wakeup pin polarity (rising or falling edge).
+ (++) PinPull: Wakeup pin pull (no pull, pull-up or pull-down).
+ [..]
+ The wakeup pins are internally connected to the EXTI lines [55-60] to
+ generate an interrupt if enabled. The EXTI lines configuration is done by
+ the HAL_EXTI_Dx_EventInputConfig() functions defined in the stm32h7xxhal.c
+ file.
+ [..]
+ When a wakeup pin event is received the HAL_PWREx_WAKEUP_PIN_IRQHandler is
+ called and the appropriate flag is set in the PWR_WKUPFR register. Then in
+ the HAL_PWREx_WAKEUP_PIN_IRQHandler function the wakeup pin flag will be
+ cleared and the appropriate user callback will be called. The user can add
+ his own code by customization of function pointer HAL_PWREx_WKUPx_Callback.
+
+@endverbatim
+ * @{
+ */
+
+#if defined (PWR_CPUCR_RETDS_CD)
+/**
+ * @brief Enter the system to STOP mode with main domain in DSTOP2.
+ * @note In STOP mode, the domain bus matrix clock is stalled.
+ * @note In STOP mode, memories and registers are maintained and peripherals
+ * in CPU domain are no longer operational.
+ * @note All clocks in the VCORE domain are stopped, the PLL, the HSI and the
+ * HSE oscillators are disabled. Only Peripherals that have wakeup
+ * capability can switch on the HSI to receive a frame, and switch off
+ * the HSI after receiving the frame if it is not a wakeup frame. In
+ * this case the HSI clock is propagated only to the peripheral
+ * requesting it.
+ * @note When exiting STOP mode by issuing an interrupt or a wakeup event,
+ * the HSI RC oscillator is selected as system clock if STOPWUCK bit in
+ * RCC_CFGR register is set.
+ * @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
+ * intrinsic 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_PWREx_EnterSTOP2Mode (uint32_t Regulator, uint8_t STOPEntry)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_REGULATOR (Regulator));
+ assert_param (IS_PWR_STOP_ENTRY (STOPEntry));
+
+ /* Select the regulator state in Stop mode */
+ MODIFY_REG (PWR->CR1, PWR_CR1_LPDS, Regulator);
+
+ /* Go to DStop2 mode (deep retention) when CPU domain enters Deepsleep */
+ SET_BIT (PWR->CPUCR, PWR_CPUCR_RETDS_CD);
+
+ /* Keep DSTOP mode when SmartRun domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_SRD);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* Ensure that all instructions are done before entering STOP mode */
+ __ISB ();
+ __DSB ();
+
+ /* Select Stop mode entry */
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI ();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __WFE ();
+ }
+
+ /* Clear SLEEPDEEP bit of Cortex-Mx in the System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+}
+#endif /* defined (PWR_CPUCR_RETDS_CD) */
+
+/**
+ * @brief Enter a Domain to DSTOP mode.
+ * @note This API gives flexibility to manage independently each domain STOP
+ * mode. For dual core lines, this API should be executed with the
+ * corresponding Cortex-Mx to enter domain to DSTOP mode. When it is
+ * executed by all available Cortex-Mx, the system enter to STOP mode.
+ * For single core lines, calling this API with domain parameter set to
+ * PWR_D1_DOMAIN (D1/CD), the whole system will enter in STOP mode
+ * independently of PWR_CPUCR_PDDS_Dx bits values if RUN_D3 bit in the
+ * CPUCR_RUN_D3 is cleared.
+ * @note In DStop mode the domain bus matrix clock is stopped.
+ * @note The system D3/SRD domain enter Stop mode only when the CPU subsystem
+ * is in CStop mode, the EXTI wakeup sources are inactive and at least
+ * one PDDS_Dn bit in PWR CPU control register (PWR_CPUCR) for
+ * any domain request Stop.
+ * @note Before entering DSTOP mode it is recommended to call SCB_CleanDCache
+ * function in order to clean the D-Cache and guarantee the data
+ * integrity for the SRAM memories.
+ * @note In System Stop mode, the domain peripherals that use the LSI or LSE
+ * clock, and the peripherals that have a kernel clock request to
+ * select HSI or CSI as source, are still able to operate.
+ * @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
+ * intrinsic 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.
+ * @param Domain : Specifies the Domain to enter in DSTOP mode.
+ * This parameter can be one of the following values:
+ * @arg PWR_D1_DOMAIN : Enter D1/CD Domain to DSTOP mode.
+ * @arg PWR_D2_DOMAIN : Enter D2 Domain to DSTOP mode.
+ * @arg PWR_D3_DOMAIN : Enter D3/SRD Domain to DSTOP mode.
+ * @retval None.
+ */
+void HAL_PWREx_EnterSTOPMode (uint32_t Regulator, uint8_t STOPEntry, uint32_t Domain)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_REGULATOR (Regulator));
+ assert_param (IS_PWR_STOP_ENTRY (STOPEntry));
+ assert_param (IS_PWR_DOMAIN (Domain));
+
+ /* Select the regulator state in Stop mode */
+ MODIFY_REG (PWR->CR1, PWR_CR1_LPDS, Regulator);
+
+ /* Select the domain Power Down DeepSleep */
+ if (Domain == PWR_D1_DOMAIN)
+ {
+#if defined (DUAL_CORE)
+ /* Check current core */
+ if (HAL_GetCurrentCPUID () != CM7_CPUID)
+ {
+ /*
+ When the domain selected and the cortex-mx don't match, entering stop
+ mode will not be performed
+ */
+ return;
+ }
+#endif /* defined (DUAL_CORE) */
+
+ /* Keep DSTOP mode when D1/CD domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D1);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* Ensure that all instructions are done before entering STOP mode */
+ __DSB ();
+ __ISB ();
+
+ /* Select Stop mode entry */
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI ();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __WFE ();
+ }
+
+ /* Clear SLEEPDEEP bit of Cortex-Mx in the System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+ }
+#if defined (PWR_CPUCR_PDDS_D2)
+ else if (Domain == PWR_D2_DOMAIN)
+ {
+#if defined (DUAL_CORE)
+ /* Check current core */
+ if (HAL_GetCurrentCPUID () != CM4_CPUID)
+ {
+ /*
+ When the domain selected and the cortex-mx don't match, entering stop
+ mode will not be performed
+ */
+ return;
+ }
+
+ /* Keep DSTOP mode when D2 domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPU2CR, PWR_CPU2CR_PDDS_D2);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* Ensure that all instructions are done before entering STOP mode */
+ __DSB ();
+ __ISB ();
+
+ /* Select Stop mode entry */
+ if (STOPEntry == PWR_STOPENTRY_WFI)
+ {
+ /* Request Wait For Interrupt */
+ __WFI ();
+ }
+ else
+ {
+ /* Request Wait For Event */
+ __WFE ();
+ }
+
+ /* Clear SLEEPDEEP bit of Cortex-Mx in the System Control Register */
+ CLEAR_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+#else
+ /* Keep DSTOP mode when D2 domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D2);
+#endif /* defined (DUAL_CORE) */
+ }
+#endif /* defined (PWR_CPUCR_PDDS_D2) */
+ else
+ {
+#if defined (DUAL_CORE)
+ /* Check current core */
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+ {
+ /* Keep DSTOP mode when D3 domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D3);
+ }
+ else
+ {
+ /* Keep DSTOP mode when D3 domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPU2CR, PWR_CPU2CR_PDDS_D3);
+ }
+#else
+ /* Keep DSTOP mode when D3/SRD domain enters Deepsleep */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D3);
+#endif /* defined (DUAL_CORE) */
+ }
+}
+
+/**
+ * @brief Clear pending event.
+ * @note This API clears the pending event in order to enter a given CPU
+ * to CSLEEP or CSTOP. It should be called just before APIs performing
+ * enter low power mode using Wait For Event request.
+ * @note Cortex-M7 must be in CRUN mode when calling this API by Cortex-M4.
+ * @retval None.
+ */
+void HAL_PWREx_ClearPendingEvent (void)
+{
+#if defined (DUAL_CORE)
+ /* Check the current Core */
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+ {
+ __WFE ();
+ }
+ else
+ {
+ __SEV ();
+ __WFE ();
+ }
+#else
+ __WFE ();
+#endif /* defined (DUAL_CORE) */
+}
+
+/**
+ * @brief Enter a Domain to DSTANDBY mode.
+ * @note This API gives flexibility to manage independently each domain
+ * STANDBY mode. For dual core lines, this API should be executed with
+ * the corresponding Cortex-Mx to enter domain to DSTANDBY mode. When
+ * it is executed by all available Cortex-Mx, the system enter STANDBY
+ * mode.
+ * For single core lines, calling this API with D1/SRD the selected
+ * domain will enter the whole system in STOP if PWR_CPUCR_PDDS_D3 = 0
+ * and enter the whole system in STANDBY if PWR_CPUCR_PDDS_D3 = 1.
+ * @note The DStandby mode is entered when all PDDS_Dn bits in PWR_CPUCR for
+ * the Dn domain select Standby mode. When the system enters Standby
+ * mode, the voltage regulator is disabled.
+ * @note When D2 or D3 domain is in DStandby mode and the CPU sets the
+ * domain PDDS_Dn bit to select Stop mode, the domain remains in
+ * DStandby mode. The domain will only exit DStandby when the CPU
+ * allocates a peripheral in the domain.
+ * @note The system D3/SRD domain enters Standby mode only when the D1 and D2
+ * domain are in DStandby.
+ * @note Before entering DSTANDBY mode it is recommended to call
+ * SCB_CleanDCache function in order to clean the D-Cache and guarantee
+ * the data integrity for the SRAM memories.
+ * @param Domain : Specifies the Domain to enter to STANDBY mode.
+ * This parameter can be one of the following values:
+ * @arg PWR_D1_DOMAIN: Enter D1/CD Domain to DSTANDBY mode.
+ * @arg PWR_D2_DOMAIN: Enter D2 Domain to DSTANDBY mode.
+ * @arg PWR_D3_DOMAIN: Enter D3/SRD Domain to DSTANDBY mode.
+ * @retval None
+ */
+void HAL_PWREx_EnterSTANDBYMode (uint32_t Domain)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_DOMAIN (Domain));
+
+ /* Select the domain Power Down DeepSleep */
+ if (Domain == PWR_D1_DOMAIN)
+ {
+#if defined (DUAL_CORE)
+ /* Check current core */
+ if (HAL_GetCurrentCPUID () != CM7_CPUID)
+ {
+ /*
+ When the domain selected and the cortex-mx don't match, entering
+ standby mode will not be performed
+ */
+ return;
+ }
+#endif /* defined (DUAL_CORE) */
+
+ /* Allow DSTANDBY mode when D1/CD domain enters Deepsleep */
+ SET_BIT (PWR-> CPUCR, PWR_CPUCR_PDDS_D1);
+
+#if defined (DUAL_CORE)
+ /* Allow DSTANDBY mode when D1/CD domain enters Deepsleep */
+ SET_BIT (PWR-> CPU2CR, PWR_CPU2CR_PDDS_D1);
+#endif /*DUAL_CORE*/
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* This option is used to ensure that store operations are completed */
+#if defined (__CC_ARM)
+ __force_stores ();
+#endif /* defined (__CC_ARM) */
+
+ /* Request Wait For Interrupt */
+ __WFI ();
+ }
+#if defined (PWR_CPUCR_PDDS_D2)
+ else if (Domain == PWR_D2_DOMAIN)
+ {
+ /* Allow DSTANDBY mode when D2 domain enters Deepsleep */
+ SET_BIT (PWR-> CPUCR, PWR_CPUCR_PDDS_D2);
+
+#if defined (DUAL_CORE)
+ /* Check current core */
+ if (HAL_GetCurrentCPUID () != CM4_CPUID)
+ {
+ /*
+ When the domain selected and the cortex-mx don't match, entering
+ standby mode will not be performed
+ */
+ return;
+ }
+
+ /* Allow DSTANDBY mode when D2 domain enters Deepsleep */
+ SET_BIT (PWR-> CPU2CR, PWR_CPU2CR_PDDS_D2);
+
+ /* Set SLEEPDEEP bit of Cortex System Control Register */
+ SET_BIT (SCB->SCR, SCB_SCR_SLEEPDEEP_Msk);
+
+ /* This option is used to ensure that store operations are completed */
+#if defined (__CC_ARM)
+ __force_stores ();
+#endif /* defined (__CC_ARM) */
+
+ /* Request Wait For Interrupt */
+ __WFI ();
+#endif /* defined (DUAL_CORE) */
+ }
+#endif /* defined (PWR_CPUCR_PDDS_D2) */
+ else
+ {
+ /* Allow DSTANDBY mode when D3/SRD domain enters Deepsleep */
+ SET_BIT (PWR->CPUCR, PWR_CPUCR_PDDS_D3);
+
+#if defined (DUAL_CORE)
+ /* Allow DSTANDBY mode when D3/SRD domain enters Deepsleep */
+ SET_BIT (PWR->CPU2CR, PWR_CPU2CR_PDDS_D3);
+#endif /* defined (DUAL_CORE) */
+ }
+}
+
+/**
+ * @brief Configure the D3/SRD Domain state when the System in low power mode.
+ * @param D3State : Specifies the D3/SRD state.
+ * This parameter can be one of the following values :
+ * @arg PWR_D3_DOMAIN_STOP : D3/SRD domain will follow the most deep
+ * CPU sub-system low power mode.
+ * @arg PWR_D3_DOMAIN_RUN : D3/SRD domain will stay in RUN mode
+ * regardless of the CPU sub-system low
+ * power mode.
+ * @retval None
+ */
+void HAL_PWREx_ConfigD3Domain (uint32_t D3State)
+{
+ /* Check the parameter */
+ assert_param (IS_D3_STATE (D3State));
+
+ /* Keep D3/SRD in run mode */
+ MODIFY_REG (PWR->CPUCR, PWR_CPUCR_RUN_D3, D3State);
+}
+
+#if defined (DUAL_CORE)
+/**
+ * @brief Clear HOLD2F, HOLD1F, STOPF, SBF, SBF_D1, and SBF_D2 flags for a
+ * given domain.
+ * @param DomainFlags : Specifies the Domain flags to be cleared.
+ * This parameter can be one of the following values:
+ * @arg PWR_D1_DOMAIN_FLAGS : Clear D1 Domain flags.
+ * @arg PWR_D2_DOMAIN_FLAGS : Clear D2 Domain flags.
+ * @arg PWR_ALL_DOMAIN_FLAGS : Clear D1 and D2 Domain flags.
+ * @retval None.
+ */
+void HAL_PWREx_ClearDomainFlags (uint32_t DomainFlags)
+{
+ /* Check the parameter */
+ assert_param (IS_PWR_DOMAIN_FLAG (DomainFlags));
+
+ /* D1 CPU flags */
+ if (DomainFlags == PWR_D1_DOMAIN_FLAGS)
+ {
+ /* Clear D1 domain flags (HOLD2F, STOPF, SBF, SBF_D1, and SBF_D2) */
+ SET_BIT (PWR->CPUCR, PWR_CPUCR_CSSF);
+ }
+ /* D2 CPU flags */
+ else if (DomainFlags == PWR_D2_DOMAIN_FLAGS)
+ {
+ /* Clear D2 domain flags (HOLD1F, STOPF, SBF, SBF_D1, and SBF_D2) */
+ SET_BIT (PWR->CPU2CR, PWR_CPU2CR_CSSF);
+ }
+ else
+ {
+ /* Clear D1 domain flags (HOLD2F, STOPF, SBF, SBF_D1, and SBF_D2) */
+ SET_BIT (PWR->CPUCR, PWR_CPUCR_CSSF);
+ /* Clear D2 domain flags (HOLD1F, STOPF, SBF, SBF_D1, and SBF_D2) */
+ SET_BIT (PWR->CPU2CR, PWR_CPU2CR_CSSF);
+ }
+}
+
+/**
+ * @brief Hold the CPU and their domain peripherals when exiting STOP mode.
+ * @param CPU : Specifies the core to be held.
+ * This parameter can be one of the following values:
+ * @arg PWR_CORE_CPU1: Hold CPU1 and set CPU2 as master.
+ * @arg PWR_CORE_CPU2: Hold CPU2 and set CPU1 as master.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_PWREx_HoldCore (uint32_t CPU)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param (IS_PWR_CORE (CPU));
+
+ /* Check CPU index */
+ if (CPU == PWR_CORE_CPU2)
+ {
+ /* If CPU1 is not held */
+ if ((PWR->CPU2CR & PWR_CPU2CR_HOLD1) != PWR_CPU2CR_HOLD1)
+ {
+ /* Set HOLD2 bit */
+ SET_BIT (PWR->CPUCR, PWR_CPUCR_HOLD2);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* If CPU2 is not held */
+ if ((PWR->CPUCR & PWR_CPUCR_HOLD2) != PWR_CPUCR_HOLD2)
+ {
+ /* Set HOLD1 bit */
+ SET_BIT (PWR->CPU2CR, PWR_CPU2CR_HOLD1);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Release the CPU and their domain peripherals after a wake-up from
+ * STOP mode.
+ * @param CPU: Specifies the core to be released.
+ * This parameter can be one of the following values:
+ * @arg PWR_CORE_CPU1: Release the CPU1 and their domain
+ * peripherals from holding.
+ * @arg PWR_CORE_CPU2: Release the CPU2 and their domain
+ * peripherals from holding.
+ * @retval None
+ */
+void HAL_PWREx_ReleaseCore (uint32_t CPU)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_CORE (CPU));
+
+ /* Check CPU index */
+ if (CPU == PWR_CORE_CPU2)
+ {
+ /* Reset HOLD2 bit */
+ CLEAR_BIT (PWR->CPUCR, PWR_CPUCR_HOLD2);
+ }
+ else
+ {
+ /* Reset HOLD1 bit */
+ CLEAR_BIT (PWR->CPU2CR, PWR_CPU2CR_HOLD1);
+ }
+}
+#endif /* defined (DUAL_CORE) */
+
+
+/**
+ * @brief Enable the Flash Power Down in Stop mode.
+ * @note When Flash Power Down is enabled the Flash memory enters low-power
+ * mode when D1/SRD domain is in DStop mode. This feature allows to
+ * obtain the best trade-off between low-power consumption and restart
+ * time when exiting from DStop mode.
+ * @retval None.
+ */
+void HAL_PWREx_EnableFlashPowerDown (void)
+{
+ /* Enable the Flash Power Down */
+ SET_BIT (PWR->CR1, PWR_CR1_FLPS);
+}
+
+/**
+ * @brief Disable the Flash Power Down in Stop mode.
+ * @note When Flash Power Down is disabled the Flash memory is kept on
+ * normal mode when D1/SRD domain is in DStop mode. This feature allows
+ * to obtain the best trade-off between low-power consumption and
+ * restart time when exiting from DStop mode.
+ * @retval None.
+ */
+void HAL_PWREx_DisableFlashPowerDown (void)
+{
+ /* Disable the Flash Power Down */
+ CLEAR_BIT (PWR->CR1, PWR_CR1_FLPS);
+}
+
+#if defined (PWR_CR1_SRDRAMSO)
+/**
+ * @brief Enable memory block shut-off in DStop or DStop2 modes
+ * @note In DStop or DStop2 mode, the content of the memory blocks is
+ * maintained. Further power optimization can be obtained by switching
+ * off some memory blocks. This optimization implies loss of the memory
+ * content. The user can select which memory is discarded during STOP
+ * mode by means of xxSO bits.
+ * @param MemoryBlock : Specifies the memory block to shut-off during DStop or
+ * DStop2 mode.
+ * This parameter can be one of the following values:
+ * @arg PWR_SRD_AHB_MEMORY_BLOCK : SmartRun domain AHB memory.
+ * @arg PWR_USB_FDCAN_MEMORY_BLOCK : High-speed interfaces USB and
+ * FDCAN memories.
+ * @arg PWR_GFXMMU_JPEG_MEMORY_BLOCK : GFXMMU and JPEG memories.
+ * @arg PWR_TCM_ECM_MEMORY_BLOCK : Instruction TCM and ETM memories.
+ * @arg PWR_RAM1_AHB_MEMORY_BLOCK : AHB RAM1 memory.
+ * @arg PWR_RAM2_AHB_MEMORY_BLOCK : AHB RAM2 memory.
+ * @arg PWR_RAM1_AXI_MEMORY_BLOCK : AXI RAM1 memory.
+ * @arg PWR_RAM2_AXI_MEMORY_BLOCK : AXI RAM2 memory.
+ * @arg PWR_RAM3_AXI_MEMORY_BLOCK : AXI RAM3 memory.
+ * @retval None.
+ */
+void HAL_PWREx_EnableMemoryShutOff (uint32_t MemoryBlock)
+{
+ /* Check the parameter */
+ assert_param (IS_PWR_MEMORY_BLOCK (MemoryBlock));
+
+ /* Enable memory block shut-off */
+ SET_BIT (PWR->CR1, MemoryBlock);
+}
+
+/**
+ * @brief Disable memory block shut-off in DStop or DStop2 modes
+ * @param MemoryBlock : Specifies the memory block to keep content during
+ * DStop or DStop2 mode.
+ * This parameter can be one of the following values:
+ * @arg PWR_SRD_AHB_MEMORY_BLOCK : SmartRun domain AHB memory.
+ * @arg PWR_USB_FDCAN_MEMORY_BLOCK : High-speed interfaces USB and
+ * FDCAN memories.
+ * @arg PWR_GFXMMU_JPEG_MEMORY_BLOCK : GFXMMU and JPEG memories.
+ * @arg PWR_TCM_ECM_MEMORY_BLOCK : Instruction TCM and ETM memories.
+ * @arg PWR_RAM1_AHB_MEMORY_BLOCK : AHB RAM1 memory.
+ * @arg PWR_RAM2_AHB_MEMORY_BLOCK : AHB RAM2 memory.
+ * @arg PWR_RAM1_AXI_MEMORY_BLOCK : AXI RAM1 memory.
+ * @arg PWR_RAM2_AXI_MEMORY_BLOCK : AXI RAM2 memory.
+ * @arg PWR_RAM3_AXI_MEMORY_BLOCK : AXI RAM3 memory.
+ * @retval None.
+ */
+void HAL_PWREx_DisableMemoryShutOff (uint32_t MemoryBlock)
+{
+ /* Check the parameter */
+ assert_param (IS_PWR_MEMORY_BLOCK (MemoryBlock));
+
+ /* Disable memory block shut-off */
+ CLEAR_BIT (PWR->CR1, MemoryBlock);
+}
+#endif /* defined (PWR_CR1_SRDRAMSO) */
+
+/**
+ * @brief Enable the Wake-up PINx functionality.
+ * @param sPinParams : Pointer to a PWREx_WakeupPinTypeDef structure that
+ * contains the configuration information for the wake-up
+ * Pin.
+ * @note For dual core devices, please ensure to configure the EXTI lines for
+ * the different Cortex-Mx. All combination are allowed: wake up only
+ * Cortex-M7, wake up only Cortex-M4 and wake up Cortex-M7 and
+ * Cortex-M4.
+ * @retval None.
+ */
+void HAL_PWREx_EnableWakeUpPin (const PWREx_WakeupPinTypeDef *sPinParams)
+{
+ uint32_t pinConfig;
+ uint32_t regMask;
+ const uint32_t pullMask = PWR_WKUPEPR_WKUPPUPD1;
+
+ /* Check the parameters */
+ assert_param (IS_PWR_WAKEUP_PIN (sPinParams->WakeUpPin));
+ assert_param (IS_PWR_WAKEUP_PIN_POLARITY (sPinParams->PinPolarity));
+ assert_param (IS_PWR_WAKEUP_PIN_PULL (sPinParams->PinPull));
+
+ pinConfig = sPinParams->WakeUpPin | \
+ (sPinParams->PinPolarity << ((POSITION_VAL(sPinParams->WakeUpPin) + PWR_WKUPEPR_WKUPP1_Pos) & 0x1FU)) | \
+ (sPinParams->PinPull << (((POSITION_VAL(sPinParams->WakeUpPin) * PWR_WAKEUP_PINS_PULL_SHIFT_OFFSET) + PWR_WKUPEPR_WKUPPUPD1_Pos) & 0x1FU));
+
+ regMask = sPinParams->WakeUpPin | \
+ (PWR_WKUPEPR_WKUPP1 << (POSITION_VAL(sPinParams->WakeUpPin) & 0x1FU)) | \
+ (pullMask << ((POSITION_VAL(sPinParams->WakeUpPin) * PWR_WAKEUP_PINS_PULL_SHIFT_OFFSET) & 0x1FU));
+
+ /* Enable and Specify the Wake-Up pin polarity and the pull configuration
+ for the event detection (rising or falling edge) */
+ MODIFY_REG (PWR->WKUPEPR, regMask, pinConfig);
+#ifndef DUAL_CORE
+ /* Configure the Wakeup Pin EXTI Line */
+ MODIFY_REG (EXTI->IMR2, PWR_EXTI_WAKEUP_PINS_MASK, (sPinParams->WakeUpPin << EXTI_IMR2_IM55_Pos));
+#endif /* !DUAL_CORE */
+}
+
+/**
+ * @brief Disable the Wake-up PINx functionality.
+ * @param WakeUpPin : Specifies the Wake-Up pin to be disabled.
+ * This parameter can be one of the following values:
+ * @arg PWR_WAKEUP_PIN1 : Disable PA0 wake-up PIN.
+ * @arg PWR_WAKEUP_PIN2 : Disable PA2 wake-up PIN.
+ * @arg PWR_WAKEUP_PIN3 : Disable PI8 wake-up PIN.
+ * @arg PWR_WAKEUP_PIN4 : Disable PC13 wake-up PIN.
+ * @arg PWR_WAKEUP_PIN5 : Disable PI11 wake-up PIN.
+ * @arg PWR_WAKEUP_PIN6 : Disable PC1 wake-up PIN.
+ * @note The PWR_WAKEUP_PIN3 and PWR_WAKEUP_PIN5 are available only for
+ * devices that support GPIOI port.
+ * @retval None
+ */
+void HAL_PWREx_DisableWakeUpPin (uint32_t WakeUpPin)
+{
+ /* Check the parameter */
+ assert_param (IS_PWR_WAKEUP_PIN (WakeUpPin));
+
+ /* Disable the WakeUpPin */
+ CLEAR_BIT (PWR->WKUPEPR, WakeUpPin);
+}
+
+/**
+ * @brief Get the Wake-Up Pin pending flags.
+ * @param WakeUpFlag : Specifies the Wake-Up PIN flag to be checked.
+ * This parameter can be one of the following values:
+ * @arg PWR_WAKEUP_FLAG1 : Get wakeup event received from PA0.
+ * @arg PWR_WAKEUP_FLAG2 : Get wakeup event received from PA2.
+ * @arg PWR_WAKEUP_FLAG3 : Get wakeup event received from PI8.
+ * @arg PWR_WAKEUP_FLAG4 : Get wakeup event received from PC13.
+ * @arg PWR_WAKEUP_FLAG5 : Get wakeup event received from PI11.
+ * @arg PWR_WAKEUP_FLAG6 : Get wakeup event received from PC1.
+ * @arg PWR_WAKEUP_FLAG_ALL : Get Wakeup event received from all
+ * wake up pins.
+ * @note The PWR_WAKEUP_FLAG3 and PWR_WAKEUP_FLAG5 are available only for
+ * devices that support GPIOI port.
+ * @retval The Wake-Up pin flag.
+ */
+uint32_t HAL_PWREx_GetWakeupFlag (uint32_t WakeUpFlag)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_WAKEUP_FLAG (WakeUpFlag));
+
+ /* Return the wake up pin flag */
+ return (PWR->WKUPFR & WakeUpFlag);
+}
+
+/**
+ * @brief Clear the Wake-Up pin pending flag.
+ * @param WakeUpFlag: Specifies the Wake-Up PIN flag to clear.
+ * This parameter can be one of the following values:
+ * @arg PWR_WAKEUP_FLAG1 : Clear the wakeup event received from PA0.
+ * @arg PWR_WAKEUP_FLAG2 : Clear the wakeup event received from PA2.
+ * @arg PWR_WAKEUP_FLAG3 : Clear the wakeup event received from PI8.
+ * @arg PWR_WAKEUP_FLAG4 : Clear the wakeup event received from PC13.
+ * @arg PWR_WAKEUP_FLAG5 : Clear the wakeup event received from PI11.
+ * @arg PWR_WAKEUP_FLAG6 : Clear the wakeup event received from PC1.
+ * @arg PWR_WAKEUP_FLAG_ALL : Clear the wakeup events received from
+ * all wake up pins.
+ * @note The PWR_WAKEUP_FLAG3 and PWR_WAKEUP_FLAG5 are available only for
+ * devices that support GPIOI port.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_ClearWakeupFlag (uint32_t WakeUpFlag)
+{
+ /* Check the parameter */
+ assert_param (IS_PWR_WAKEUP_FLAG (WakeUpFlag));
+
+ /* Clear the wake up event received from wake up pin x */
+ SET_BIT (PWR->WKUPCR, WakeUpFlag);
+
+ /* Check if the wake up event is well cleared */
+ if ((PWR->WKUPFR & WakeUpFlag) != 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief This function handles the PWR WAKEUP PIN interrupt request.
+ * @note This API should be called under the WAKEUP_PIN_IRQHandler().
+ * @retval None.
+ */
+void HAL_PWREx_WAKEUP_PIN_IRQHandler (void)
+{
+ /* Wakeup pin EXTI line interrupt detected */
+ if (READ_BIT(PWR->WKUPFR, PWR_WKUPFR_WKUPF1) != 0U)
+ {
+ /* Clear PWR WKUPF1 flag */
+ __HAL_PWR_CLEAR_WAKEUPFLAG (PWR_FLAG_WKUP1);
+
+ /* PWR WKUP1 interrupt user callback */
+ HAL_PWREx_WKUP1_Callback ();
+ }
+ else if (READ_BIT (PWR->WKUPFR, PWR_WKUPFR_WKUPF2) != 0U)
+ {
+ /* Clear PWR WKUPF2 flag */
+ __HAL_PWR_CLEAR_WAKEUPFLAG (PWR_FLAG_WKUP2);
+
+ /* PWR WKUP2 interrupt user callback */
+ HAL_PWREx_WKUP2_Callback ();
+ }
+#if defined (PWR_WKUPFR_WKUPF3)
+ else if (READ_BIT (PWR->WKUPFR, PWR_WKUPFR_WKUPF3) != 0U)
+ {
+ /* Clear PWR WKUPF3 flag */
+ __HAL_PWR_CLEAR_WAKEUPFLAG (PWR_FLAG_WKUP3);
+
+ /* PWR WKUP3 interrupt user callback */
+ HAL_PWREx_WKUP3_Callback ();
+ }
+#endif /* defined (PWR_WKUPFR_WKUPF3) */
+ else if (READ_BIT (PWR->WKUPFR, PWR_WKUPFR_WKUPF4) != 0U)
+ {
+ /* Clear PWR WKUPF4 flag */
+ __HAL_PWR_CLEAR_WAKEUPFLAG (PWR_FLAG_WKUP4);
+
+ /* PWR WKUP4 interrupt user callback */
+ HAL_PWREx_WKUP4_Callback ();
+ }
+#if defined (PWR_WKUPFR_WKUPF5)
+ else if (READ_BIT (PWR->WKUPFR, PWR_WKUPFR_WKUPF5) != 0U)
+ {
+ /* Clear PWR WKUPF5 flag */
+ __HAL_PWR_CLEAR_WAKEUPFLAG (PWR_FLAG_WKUP5);
+
+ /* PWR WKUP5 interrupt user callback */
+ HAL_PWREx_WKUP5_Callback ();
+ }
+#endif /* defined (PWR_WKUPFR_WKUPF5) */
+ else
+ {
+ /* Clear PWR WKUPF6 flag */
+ __HAL_PWR_CLEAR_WAKEUPFLAG (PWR_FLAG_WKUP6);
+
+ /* PWR WKUP6 interrupt user callback */
+ HAL_PWREx_WKUP6_Callback ();
+ }
+}
+
+/**
+ * @brief PWR WKUP1 interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_WKUP1_Callback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWREx_WKUP1Callback can be implemented in the user file
+ */
+}
+
+/**
+ * @brief PWR WKUP2 interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_WKUP2_Callback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWREx_WKUP2Callback can be implemented in the user file
+ */
+}
+
+#if defined (PWR_WKUPFR_WKUPF3)
+/**
+ * @brief PWR WKUP3 interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_WKUP3_Callback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWREx_WKUP3Callback can be implemented in the user file
+ */
+}
+#endif /* defined (PWR_WKUPFR_WKUPF3) */
+
+/**
+ * @brief PWR WKUP4 interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_WKUP4_Callback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWREx_WKUP4Callback can be implemented in the user file
+ */
+}
+
+#if defined (PWR_WKUPFR_WKUPF5)
+/**
+ * @brief PWR WKUP5 interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_WKUP5_Callback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWREx_WKUP5Callback can be implemented in the user file
+ */
+}
+#endif /* defined (PWR_WKUPFR_WKUPF5) */
+
+/**
+ * @brief PWR WKUP6 interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_WKUP6_Callback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWREx_WKUP6Callback can be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/** @defgroup PWREx_Exported_Functions_Group3 Peripherals control functions
+ * @brief Peripherals control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripherals control functions #####
+ ===============================================================================
+
+ *** Main and Backup Regulators configuration ***
+ ================================================
+ [..]
+ (+) The backup domain includes 4 Kbytes of backup SRAM accessible only
+ from the CPU, and addressed 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_PWREx_ControlVoltageScaling(VOS) function which configure the VOS
+ bit in PWR_D3CR register.
+ (+) The main internal regulator can be configured to operate in Low Power
+ mode when the system enters STOP mode to further reduce power
+ consumption.
+ This is done through HAL_PWREx_ControlStopModeVoltageScaling(SVOS)
+ function which configure the SVOS bit in PWR_CR1 register.
+ The selected SVOS4 and SVOS5 levels add an additional startup delay
+ when exiting from system Stop mode.
+ -@- Refer to the product datasheets for more details.
+
+ *** USB Regulator configuration ***
+ ===================================
+ [..]
+ (+) The USB transceivers are supplied from a dedicated VDD33USB supply
+ that can be provided either by the integrated USB regulator, or by an
+ external USB supply.
+ (+) The USB regulator is enabled by HAL_PWREx_EnableUSBReg() function, the
+ VDD33USB is then provided from the USB regulator.
+ (+) When the USB regulator is enabled, the VDD33USB supply level detector
+ shall be enabled through HAL_PWREx_EnableUSBVoltageDetector()
+ function.
+ (+) The USB regulator is disabled through HAL_PWREx_DisableUSBReg()
+ function and VDD33USB can be provided from an external supply. In this
+ case VDD33USB and VDD50USB shall be connected together.
+
+ *** VBAT battery charging ***
+ =============================
+ [..]
+ (+) When VDD is present, the external battery connected to VBAT can be
+ charged through an internal resistance. VBAT charging can be performed
+ either through a 5 KOhm resistor or through a 1.5 KOhm resistor.
+ (+) VBAT charging is enabled by HAL_PWREx_EnableBatteryCharging
+ (ResistorValue) function with:
+ (++) ResistorValue:
+ (+++) PWR_BATTERY_CHARGING_RESISTOR_5: 5 KOhm resistor.
+ (+++) PWR_BATTERY_CHARGING_RESISTOR_1_5: 1.5 KOhm resistor.
+ (+) VBAT charging is disabled by HAL_PWREx_DisableBatteryCharging()
+ function.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the Backup Regulator.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableBkUpReg (void)
+{
+ uint32_t tickstart;
+
+ /* Enable the Backup regulator */
+ SET_BIT (PWR->CR2, PWR_CR2_BREN);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till Backup regulator ready flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_BRR) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart ) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Backup Regulator.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableBkUpReg (void)
+{
+ uint32_t tickstart;
+
+ /* Disable the Backup regulator */
+ CLEAR_BIT (PWR->CR2, PWR_CR2_BREN);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till Backup regulator ready flag is reset */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_BRR) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart ) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the USB Regulator.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_EnableUSBReg (void)
+{
+ uint32_t tickstart;
+
+ /* Enable the USB regulator */
+ SET_BIT (PWR->CR3, PWR_CR3_USBREGEN);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till the USB regulator ready flag is set */
+ while (__HAL_PWR_GET_FLAG (PWR_FLAG_USB33RDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart ) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the USB Regulator.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_PWREx_DisableUSBReg (void)
+{
+ uint32_t tickstart;
+
+ /* Disable the USB regulator */
+ CLEAR_BIT (PWR->CR3, PWR_CR3_USBREGEN);
+
+ /* Get tick */
+ tickstart = HAL_GetTick ();
+
+ /* Wait till the USB regulator ready flag is reset */
+ while(__HAL_PWR_GET_FLAG (PWR_FLAG_USB33RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart ) > PWR_FLAG_SETTING_DELAY)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Enable the USB voltage level detector.
+ * @retval None.
+ */
+void HAL_PWREx_EnableUSBVoltageDetector (void)
+{
+ /* Enable the USB voltage detector */
+ SET_BIT (PWR->CR3, PWR_CR3_USB33DEN);
+}
+
+/**
+ * @brief Disable the USB voltage level detector.
+ * @retval None.
+ */
+void HAL_PWREx_DisableUSBVoltageDetector (void)
+{
+ /* Disable the USB voltage detector */
+ CLEAR_BIT (PWR->CR3, PWR_CR3_USB33DEN);
+}
+
+/**
+ * @brief Enable the Battery charging.
+ * @note When VDD is present, charge the external battery through an internal
+ * resistor.
+ * @param ResistorValue : Specifies the charging resistor.
+ * This parameter can be one of the following values :
+ * @arg PWR_BATTERY_CHARGING_RESISTOR_5 : 5 KOhm resistor.
+ * @arg PWR_BATTERY_CHARGING_RESISTOR_1_5 : 1.5 KOhm resistor.
+ * @retval None.
+ */
+void HAL_PWREx_EnableBatteryCharging (uint32_t ResistorValue)
+{
+ /* Check the parameter */
+ assert_param (IS_PWR_BATTERY_RESISTOR_SELECT (ResistorValue));
+
+ /* Specify the charging resistor */
+ MODIFY_REG (PWR->CR3, PWR_CR3_VBRS, ResistorValue);
+
+ /* Enable the Battery charging */
+ SET_BIT (PWR->CR3, PWR_CR3_VBE);
+}
+
+/**
+ * @brief Disable the Battery charging.
+ * @retval None.
+ */
+void HAL_PWREx_DisableBatteryCharging (void)
+{
+ /* Disable the Battery charging */
+ CLEAR_BIT (PWR->CR3, PWR_CR3_VBE);
+}
+
+#if defined (PWR_CR1_BOOSTE)
+/**
+ * @brief Enable the booster to guarantee the analog switch AC performance when
+ * the VDD supply voltage is below 2V7.
+ * @note The VDD supply voltage can be monitored through the PVD and the PLS
+ * field bits.
+ * @retval None.
+ */
+void HAL_PWREx_EnableAnalogBooster (void)
+{
+ /* Enable the Analog voltage */
+ SET_BIT (PWR->CR1, PWR_CR1_AVD_READY);
+
+ /* Enable VDDA booster */
+ SET_BIT (PWR->CR1, PWR_CR1_BOOSTE);
+}
+
+/**
+ * @brief Disable the analog booster.
+ * @retval None.
+ */
+void HAL_PWREx_DisableAnalogBooster (void)
+{
+ /* Disable VDDA booster */
+ CLEAR_BIT (PWR->CR1, PWR_CR1_BOOSTE);
+
+ /* Disable the Analog voltage */
+ CLEAR_BIT (PWR->CR1, PWR_CR1_AVD_READY);
+}
+#endif /* defined (PWR_CR1_BOOSTE) */
+/**
+ * @}
+ */
+
+/** @defgroup PWREx_Exported_Functions_Group4 Power Monitoring functions
+ * @brief Power Monitoring functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Power Monitoring functions #####
+ ===============================================================================
+
+ *** VBAT and Temperature supervision ***
+ ========================================
+ [..]
+ (+) The VBAT battery voltage supply can be monitored by comparing it with
+ two threshold levels: VBAThigh and VBATlow. VBATH flag and VBATL flags
+ in the PWR control register 2 (PWR_CR2), indicate if VBAT is higher or
+ lower than the threshold.
+ (+) The temperature can be monitored by comparing it with two threshold
+ levels, TEMPhigh and TEMPlow. TEMPH and TEMPL flags, in the PWR
+ control register 2 (PWR_CR2), indicate whether the device temperature
+ is higher or lower than the threshold.
+ (+) The VBAT and the temperature monitoring is enabled by
+ HAL_PWREx_EnableMonitoring() function and disabled by
+ HAL_PWREx_DisableMonitoring() function.
+ (+) The HAL_PWREx_GetVBATLevel() function returns the VBAT level which can
+ be : PWR_VBAT_BELOW_LOW_THRESHOLD or PWR_VBAT_ABOVE_HIGH_THRESHOLD or
+ PWR_VBAT_BETWEEN_HIGH_LOW_THRESHOLD.
+ (+) The HAL_PWREx_GetTemperatureLevel() function returns the Temperature
+ level which can be :
+ PWR_TEMP_BELOW_LOW_THRESHOLD or PWR_TEMP_ABOVE_HIGH_THRESHOLD or
+ PWR_TEMP_BETWEEN_HIGH_LOW_THRESHOLD.
+
+ *** AVD configuration ***
+ =========================
+ [..]
+ (+) The AVD is used to monitor the VDDA power supply by comparing it to a
+ threshold selected by the AVD Level (ALS[3:0] bits in the PWR_CR1
+ register).
+ (+) A AVDO flag is available to indicate if VDDA is higher or lower
+ than the AVD threshold. This event is internally connected to the EXTI
+ line 16 to generate an interrupt if enabled.
+ It is configurable through __HAL_PWR_AVD_EXTI_ENABLE_IT() macro.
+ (+) The AVD is stopped in System Standby mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enable the VBAT and temperature monitoring.
+ * @retval HAL status.
+ */
+void HAL_PWREx_EnableMonitoring (void)
+{
+ /* Enable the VBAT and Temperature monitoring */
+ SET_BIT (PWR->CR2, PWR_CR2_MONEN);
+}
+
+/**
+ * @brief Disable the VBAT and temperature monitoring.
+ * @retval HAL status.
+ */
+void HAL_PWREx_DisableMonitoring (void)
+{
+ /* Disable the VBAT and Temperature monitoring */
+ CLEAR_BIT (PWR->CR2, PWR_CR2_MONEN);
+}
+
+/**
+ * @brief Indicate whether the junction temperature is between, above or below
+ * the thresholds.
+ * @retval Temperature level.
+ */
+uint32_t HAL_PWREx_GetTemperatureLevel (void)
+{
+ uint32_t tempLevel, regValue;
+
+ /* Read the temperature flags */
+ regValue = READ_BIT (PWR->CR2, (PWR_CR2_TEMPH | PWR_CR2_TEMPL));
+
+ /* Check if the temperature is below the threshold */
+ if (regValue == PWR_CR2_TEMPL)
+ {
+ tempLevel = PWR_TEMP_BELOW_LOW_THRESHOLD;
+ }
+ /* Check if the temperature is above the threshold */
+ else if (regValue == PWR_CR2_TEMPH)
+ {
+ tempLevel = PWR_TEMP_ABOVE_HIGH_THRESHOLD;
+ }
+ /* The temperature is between the thresholds */
+ else
+ {
+ tempLevel = PWR_TEMP_BETWEEN_HIGH_LOW_THRESHOLD;
+ }
+
+ return tempLevel;
+}
+
+/**
+ * @brief Indicate whether the Battery voltage level is between, above or below
+ * the thresholds.
+ * @retval VBAT level.
+ */
+uint32_t HAL_PWREx_GetVBATLevel (void)
+{
+ uint32_t VBATLevel, regValue;
+
+ /* Read the VBAT flags */
+ regValue = READ_BIT (PWR->CR2, (PWR_CR2_VBATH | PWR_CR2_VBATL));
+
+ /* Check if the VBAT is below the threshold */
+ if (regValue == PWR_CR2_VBATL)
+ {
+ VBATLevel = PWR_VBAT_BELOW_LOW_THRESHOLD;
+ }
+ /* Check if the VBAT is above the threshold */
+ else if (regValue == PWR_CR2_VBATH)
+ {
+ VBATLevel = PWR_VBAT_ABOVE_HIGH_THRESHOLD;
+ }
+ /* The VBAT is between the thresholds */
+ else
+ {
+ VBATLevel = PWR_VBAT_BETWEEN_HIGH_LOW_THRESHOLD;
+ }
+
+ return VBATLevel;
+}
+
+#if defined (PWR_CSR1_MMCVDO)
+/**
+ * @brief Get the VDDMMC voltage level.
+ * @retval The VDDMMC voltage level.
+ */
+PWREx_MMC_VoltageLevel HAL_PWREx_GetMMCVoltage (void)
+{
+ PWREx_MMC_VoltageLevel mmc_voltage;
+
+ /* Check voltage detector output on VDDMMC value */
+ if ((PWR->CSR1 & PWR_CSR1_MMCVDO_Msk) == 0U)
+ {
+ mmc_voltage = PWR_MMC_VOLTAGE_BELOW_1V2;
+ }
+ else
+ {
+ mmc_voltage = PWR_MMC_VOLTAGE_EQUAL_ABOVE_1V2;
+ }
+
+ return mmc_voltage;
+}
+#endif /* defined (PWR_CSR1_MMCVDO) */
+
+/**
+ * @brief Configure the event mode and the voltage threshold detected by the
+ * Analog Voltage Detector (AVD).
+ * @param sConfigAVD : Pointer to an PWREx_AVDTypeDef structure that contains
+ * the configuration information for the AVD.
+ * @note Refer to the electrical characteristics of your device datasheet for
+ * more details about the voltage threshold corresponding to each
+ * detection level.
+ * @note For dual core devices, please ensure to configure the EXTI lines for
+ * the different Cortex-Mx through PWR_Exported_Macro provided by this
+ * driver. All combination are allowed: wake up only Cortex-M7, wake up
+ * only Cortex-M4 and wake up Cortex-M7 and Cortex-M4.
+ * @retval None.
+ */
+void HAL_PWREx_ConfigAVD (const PWREx_AVDTypeDef *sConfigAVD)
+{
+ /* Check the parameters */
+ assert_param (IS_PWR_AVD_LEVEL (sConfigAVD->AVDLevel));
+ assert_param (IS_PWR_AVD_MODE (sConfigAVD->Mode));
+
+ /* Set the ALS[18:17] bits according to AVDLevel value */
+ MODIFY_REG (PWR->CR1, PWR_CR1_ALS, sConfigAVD->AVDLevel);
+
+ /* Clear any previous config */
+#if !defined (DUAL_CORE)
+ __HAL_PWR_AVD_EXTI_DISABLE_EVENT ();
+ __HAL_PWR_AVD_EXTI_DISABLE_IT ();
+#endif /* !defined (DUAL_CORE) */
+
+ __HAL_PWR_AVD_EXTI_DISABLE_RISING_EDGE ();
+ __HAL_PWR_AVD_EXTI_DISABLE_FALLING_EDGE ();
+
+#if !defined (DUAL_CORE)
+ /* Configure the interrupt mode */
+ if ((sConfigAVD->Mode & AVD_MODE_IT) == AVD_MODE_IT)
+ {
+ __HAL_PWR_AVD_EXTI_ENABLE_IT ();
+ }
+
+ /* Configure the event mode */
+ if ((sConfigAVD->Mode & AVD_MODE_EVT) == AVD_MODE_EVT)
+ {
+ __HAL_PWR_AVD_EXTI_ENABLE_EVENT ();
+ }
+#endif /* !defined (DUAL_CORE) */
+
+ /* Rising edge configuration */
+ if ((sConfigAVD->Mode & AVD_RISING_EDGE) == AVD_RISING_EDGE)
+ {
+ __HAL_PWR_AVD_EXTI_ENABLE_RISING_EDGE ();
+ }
+
+ /* Falling edge configuration */
+ if ((sConfigAVD->Mode & AVD_FALLING_EDGE) == AVD_FALLING_EDGE)
+ {
+ __HAL_PWR_AVD_EXTI_ENABLE_FALLING_EDGE ();
+ }
+}
+
+/**
+ * @brief Enable the Analog Voltage Detector (AVD).
+ * @retval None.
+ */
+void HAL_PWREx_EnableAVD (void)
+{
+ /* Enable the Analog Voltage Detector */
+ SET_BIT (PWR->CR1, PWR_CR1_AVDEN);
+}
+
+/**
+ * @brief Disable the Analog Voltage Detector(AVD).
+ * @retval None.
+ */
+void HAL_PWREx_DisableAVD (void)
+{
+ /* Disable the Analog Voltage Detector */
+ CLEAR_BIT (PWR->CR1, PWR_CR1_AVDEN);
+}
+
+/**
+ * @brief This function handles the PWR PVD/AVD interrupt request.
+ * @note This API should be called under the PVD_AVD_IRQHandler().
+ * @retval None
+ */
+void HAL_PWREx_PVD_AVD_IRQHandler (void)
+{
+ /* Check if the Programmable Voltage Detector is enabled (PVD) */
+ if (READ_BIT (PWR->CR1, PWR_CR1_PVDEN) != 0U)
+ {
+#if defined (DUAL_CORE)
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+#endif /* defined (DUAL_CORE) */
+ {
+ /* Check PWR D1/CD EXTI flag */
+ if (__HAL_PWR_PVD_EXTI_GET_FLAG () != 0U)
+ {
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback ();
+
+ if(__HAL_PWR_GET_FLAG (PWR_FLAG_AVDO) == 0U)
+ {
+ /* Clear PWR EXTI D1/CD pending bit */
+ __HAL_PWR_PVD_EXTI_CLEAR_FLAG ();
+ }
+ }
+ }
+#if defined (DUAL_CORE)
+ else
+ {
+ /* Check PWR EXTI D2 flag */
+ if (__HAL_PWR_PVD_EXTID2_GET_FLAG () != 0U)
+ {
+ /* PWR PVD interrupt user callback */
+ HAL_PWR_PVDCallback ();
+
+ if(__HAL_PWR_GET_FLAG (PWR_FLAG_AVDO) == 0U)
+ {
+ /* Clear PWR EXTI D2 pending bit */
+ __HAL_PWR_PVD_EXTID2_CLEAR_FLAG ();
+ }
+ }
+ }
+#endif /* defined (DUAL_CORE) */
+ }
+
+ /* Check if the Analog Voltage Detector is enabled (AVD) */
+ if (READ_BIT (PWR->CR1, PWR_CR1_AVDEN) != 0U)
+ {
+#if defined (DUAL_CORE)
+ if (HAL_GetCurrentCPUID () == CM7_CPUID)
+#endif /* defined (DUAL_CORE) */
+ {
+ /* Check PWR EXTI D1/CD flag */
+ if (__HAL_PWR_AVD_EXTI_GET_FLAG () != 0U)
+ {
+ /* PWR AVD interrupt user callback */
+ HAL_PWREx_AVDCallback ();
+
+ if(__HAL_PWR_GET_FLAG (PWR_FLAG_PVDO) == 0U)
+ {
+ /* Clear PWR EXTI D1/CD pending bit */
+ __HAL_PWR_AVD_EXTI_CLEAR_FLAG ();
+ }
+ }
+ }
+#if defined (DUAL_CORE)
+ else
+ {
+ /* Check PWR EXTI D2 flag */
+ if (__HAL_PWR_AVD_EXTID2_GET_FLAG () != 0U)
+ {
+ /* PWR AVD interrupt user callback */
+ HAL_PWREx_AVDCallback ();
+
+ if(__HAL_PWR_GET_FLAG (PWR_FLAG_PVDO) == 0U)
+ {
+ /* Clear PWR EXTI D2 pending bit */
+ __HAL_PWR_AVD_EXTID2_CLEAR_FLAG ();
+ }
+ }
+ }
+#endif /* defined (DUAL_CORE) */
+ }
+}
+
+/**
+ * @brief PWR AVD interrupt callback.
+ * @retval None.
+ */
+__weak void HAL_PWREx_AVDCallback (void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_PWR_AVDCallback can be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c
new file mode 100755
index 0000000..074ff74
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c
@@ -0,0 +1,2752 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_qspi.c
+ * @author MCD Application Team
+ * @brief QSPI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the QuadSPI interface (QSPI).
+ * + Initialization and de-initialization functions
+ * + Indirect functional mode management
+ * + Memory-mapped functional mode management
+ * + Auto-polling functional mode management
+ * + Interrupts and flags management
+ * + MDMA channel configuration for indirect functional mode
+ * + Errors management and abort functionality
+ *
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ===============================================================================
+ ##### How to use this driver #####
+ ===============================================================================
+ [..]
+ *** Initialization ***
+ ======================
+ [..]
+ (#) As prerequisite, fill in the HAL_QSPI_MspInit() :
+ (++) Enable QuadSPI clock interface with __HAL_RCC_QSPI_CLK_ENABLE().
+ (++) Reset QuadSPI Peripheral with __HAL_RCC_QSPI_FORCE_RESET() and __HAL_RCC_QSPI_RELEASE_RESET().
+ (++) Enable the clocks for the QuadSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
+ (++) Configure these QuadSPI pins in alternate mode using HAL_GPIO_Init().
+ (++) If interrupt mode is used, enable and configure QuadSPI global
+ interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (++) If DMA mode is used, enable the clocks for the QuadSPI MDMA
+ with __HAL_RCC_MDMA_CLK_ENABLE(), configure MDMA with HAL_MDMA_Init(),
+ link it with QuadSPI handle using __HAL_LINKDMA(), enable and configure
+ MDMA global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
+ (#) Configure the flash size, the clock prescaler, the fifo threshold, the
+ clock mode, the sample shifting and the CS high time using the HAL_QSPI_Init() function.
+
+ *** Indirect functional mode ***
+ ================================
+ [..]
+ (#) Configure the command sequence using the HAL_QSPI_Command() or HAL_QSPI_Command_IT()
+ functions :
+ (++) Instruction phase : the mode used and if present the instruction opcode.
+ (++) Address phase : the mode used and if present the size and the address value.
+ (++) Alternate-bytes phase : the mode used and if present the size and the alternate
+ bytes values.
+ (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
+ (++) Data phase : the mode used and if present the number of bytes.
+ (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay
+ if activated.
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (#) If no data is required for the command, it is sent directly to the memory :
+ (++) In polling mode, the output of the function is done when the transfer is complete.
+ (++) In interrupt mode, HAL_QSPI_CmdCpltCallback() will be called when the transfer is complete.
+ (#) For the indirect write mode, use HAL_QSPI_Transmit(), HAL_QSPI_Transmit_DMA() or
+ HAL_QSPI_Transmit_IT() after the command configuration :
+ (++) In polling mode, the output of the function is done when the transfer is complete.
+ (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold
+ is reached and HAL_QSPI_TxCpltCallback() will be called when the transfer is complete.
+ (++) In DMA mode,HAL_QSPI_TxCpltCallback() will be called when the transfer is complete.
+ (#) For the indirect read mode, use HAL_QSPI_Receive(), HAL_QSPI_Receive_DMA() or
+ HAL_QSPI_Receive_IT() after the command configuration :
+ (++) In polling mode, the output of the function is done when the transfer is complete.
+ (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold
+ is reached and HAL_QSPI_RxCpltCallback() will be called when the transfer is complete.
+ (++) In DMA mode,HAL_QSPI_RxCpltCallback() will be called when the transfer is complete.
+
+ *** Auto-polling functional mode ***
+ ====================================
+ [..]
+ (#) Configure the command sequence and the auto-polling functional mode using the
+ HAL_QSPI_AutoPolling() or HAL_QSPI_AutoPolling_IT() functions :
+ (++) Instruction phase : the mode used and if present the instruction opcode.
+ (++) Address phase : the mode used and if present the size and the address value.
+ (++) Alternate-bytes phase : the mode used and if present the size and the alternate
+ bytes values.
+ (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
+ (++) Data phase : the mode used.
+ (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay
+ if activated.
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (++) The size of the status bytes, the match value, the mask used, the match mode (OR/AND),
+ the polling interval and the automatic stop activation.
+ (#) After the configuration :
+ (++) In polling mode, the output of the function is done when the status match is reached. The
+ automatic stop is activated to avoid an infinite loop.
+ (++) In interrupt mode, HAL_QSPI_StatusMatchCallback() will be called each time the status match is reached.
+
+ *** MDMA functional mode ***
+ ====================================
+ [..]
+ (#) Configure the SourceInc and DestinationInc of MDMA parameters in the HAL_QSPI_MspInit() function :
+ (++) MDMA settings for write operation :
+ (+) The DestinationInc should be MDMA_DEST_INC_DISABLE
+ (+) The SourceInc must be a value of MDMA_Source_increment_mode (Except the MDMA_SRC_INC_DOUBLEWORD).
+ (+) The SourceDataSize must be a value of MDMA Source data size (Except the MDMA_SRC_DATASIZE_DOUBLEWORD)
+ aligned with MDMA_Source_increment_mode .
+ (+) The DestDataSize must be a value of MDMA Destination data size (Except the MDMA_DEST_DATASIZE_DOUBLEWORD)
+ (++) MDMA settings for read operation :
+ (+) The SourceInc should be MDMA_SRC_INC_DISABLE
+ (+) The DestinationInc must be a value of MDMA_Destination_increment_mode (Except the MDMA_DEST_INC_DOUBLEWORD).
+ (+) The SourceDataSize must be a value of MDMA Source data size (Except the MDMA_SRC_DATASIZE_DOUBLEWORD) .
+ (+) The DestDataSize must be a value of MDMA Destination data size (Except the MDMA_DEST_DATASIZE_DOUBLEWORD)
+ aligned with MDMA_Destination_increment_mode.
+ (++)The buffer Transfer Length (BufferTransferLength) = number of bytes in the FIFO (FifoThreshold) of the Quadspi.
+ (#)In case of wrong MDMA setting
+ (++) For write operation :
+ (+) If the DestinationInc is different to MDMA_DEST_INC_DISABLE , it will be disabled by the HAL_QSPI_Transmit_DMA().
+ (++) For read operation :
+ (+) If the SourceInc is not set to MDMA_SRC_INC_DISABLE , it will be disabled by the HAL_QSPI_Receive_DMA().
+
+ *** Memory-mapped functional mode ***
+ =====================================
+ [..]
+ (#) Configure the command sequence and the memory-mapped functional mode using the
+ HAL_QSPI_MemoryMapped() functions :
+ (++) Instruction phase : the mode used and if present the instruction opcode.
+ (++) Address phase : the mode used and the size.
+ (++) Alternate-bytes phase : the mode used and if present the size and the alternate
+ bytes values.
+ (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
+ (++) Data phase : the mode used.
+ (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay
+ if activated.
+ (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
+ (++) The timeout activation and the timeout period.
+ (#) After the configuration, the QuadSPI will be used as soon as an access on the AHB is done on
+ the address range. HAL_QSPI_TimeOutCallback() will be called when the timeout expires.
+
+ *** Errors management and abort functionality ***
+ =================================================
+ [..]
+ (#) HAL_QSPI_GetError() function gives the error raised during the last operation.
+ (#) HAL_QSPI_Abort() and HAL_QSPI_Abort_IT() functions aborts any on-going operation and
+ flushes the fifo :
+ (++) In polling mode, the output of the function is done when the transfer
+ complete bit is set and the busy bit cleared.
+ (++) In interrupt mode, HAL_QSPI_AbortCpltCallback() will be called when
+ the transfer complete bit is set.
+
+ *** Control functions ***
+ =========================
+ [..]
+ (#) HAL_QSPI_GetState() function gives the current state of the HAL QuadSPI driver.
+ (#) HAL_QSPI_SetTimeout() function configures the timeout value used in the driver.
+ (#) HAL_QSPI_SetFifoThreshold() function configures the threshold on the Fifo of the QSPI IP.
+ (#) HAL_QSPI_GetFifoThreshold() function gives the current of the Fifo's threshold
+ (#) HAL_QSPI_SetFlashID() function configures the index of the flash memory to be accessed.
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_QSPI_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions HAL_QSPI_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) ErrorCallback : callback when error occurs.
+ (+) AbortCpltCallback : callback when abort is completed.
+ (+) FifoThresholdCallback : callback when the fifo threshold is reached.
+ (+) CmdCpltCallback : callback when a command without data is completed.
+ (+) RxCpltCallback : callback when a reception transfer is completed.
+ (+) TxCpltCallback : callback when a transmission transfer is completed.
+ (+) StatusMatchCallback : callback when a status match occurs.
+ (+) TimeOutCallback : callback when the timeout perioed expires.
+ (+) MspInitCallback : QSPI MspInit.
+ (+) MspDeInitCallback : QSPI MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function HAL_QSPI_UnRegisterCallback() to reset a callback to the default
+ weak (overridden) function. It allows to reset following callbacks:
+ (+) ErrorCallback : callback when error occurs.
+ (+) AbortCpltCallback : callback when abort is completed.
+ (+) FifoThresholdCallback : callback when the fifo threshold is reached.
+ (+) CmdCpltCallback : callback when a command without data is completed.
+ (+) RxCpltCallback : callback when a reception transfer is completed.
+ (+) TxCpltCallback : callback when a transmission transfer is completed.
+ (+) StatusMatchCallback : callback when a status match occurs.
+ (+) TimeOutCallback : callback when the timeout perioed expires.
+ (+) MspInitCallback : QSPI MspInit.
+ (+) MspDeInitCallback : QSPI MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the HAL_QSPI_Init and if the state is HAL_QSPI_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (overridden) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (overridden) functions in the HAL_QSPI_Init
+ and HAL_QSPI_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_QSPI_Init and HAL_QSPI_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in READY state only.
+ Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
+ in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
+ during the Init/DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_QSPI_RegisterCallback before calling HAL_QSPI_DeInit
+ or HAL_QSPI_Init function.
+
+ When The compilation define USE_HAL_QSPI_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (overridden) callbacks are used.
+
+ *** Workarounds linked to Silicon Limitation ***
+ ====================================================
+ [..]
+ (#) Workarounds Implemented inside HAL Driver
+ (++) Extra data written in the FIFO at the end of a read transfer
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+#if defined(QUADSPI)
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup QSPI QSPI
+ * @brief QSPI HAL module driver
+ * @{
+ */
+#ifdef HAL_QSPI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+
+/* Private define ------------------------------------------------------------*/
+/** @defgroup QSPI_Private_Constants QSPI Private Constants
+ * @{
+ */
+#define QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE 0x00000000U /*!<Indirect write mode*/
+#define QSPI_FUNCTIONAL_MODE_INDIRECT_READ ((uint32_t)QUADSPI_CCR_FMODE_0) /*!<Indirect read mode*/
+#define QSPI_FUNCTIONAL_MODE_AUTO_POLLING ((uint32_t)QUADSPI_CCR_FMODE_1) /*!<Automatic polling mode*/
+#define QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED ((uint32_t)QUADSPI_CCR_FMODE) /*!<Memory-mapped mode*/
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/** @defgroup QSPI_Private_Macros QSPI Private Macros
+ * @{
+ */
+#define IS_QSPI_FUNCTIONAL_MODE(MODE) (((MODE) == QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE) || \
+ ((MODE) == QSPI_FUNCTIONAL_MODE_INDIRECT_READ) || \
+ ((MODE) == QSPI_FUNCTIONAL_MODE_AUTO_POLLING) || \
+ ((MODE) == QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED))
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+
+/* Private function prototypes -----------------------------------------------*/
+static void QSPI_DMARxCplt(MDMA_HandleTypeDef *hmdma);
+static void QSPI_DMATxCplt(MDMA_HandleTypeDef *hmdma);
+static void QSPI_DMAError(MDMA_HandleTypeDef *hmdma);
+static void QSPI_DMAAbortCplt(MDMA_HandleTypeDef *hmdma);
+static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Flag, FlagStatus State, uint32_t Tickstart, uint32_t Timeout);
+static void QSPI_Config(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t FunctionalMode);
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup QSPI_Exported_Functions QSPI Exported Functions
+ * @{
+ */
+
+/** @defgroup QSPI_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+===============================================================================
+ ##### Initialization and Configuration functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Initialize the QuadSPI.
+ (+) De-initialize the QuadSPI.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the QSPI mode according to the specified parameters
+ * in the QSPI_InitTypeDef and initialize the associated handle.
+ * @param hqspi QSPI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Init(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the QSPI handle allocation */
+ if(hqspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_ALL_INSTANCE(hqspi->Instance));
+ assert_param(IS_QSPI_CLOCK_PRESCALER(hqspi->Init.ClockPrescaler));
+ assert_param(IS_QSPI_FIFO_THRESHOLD(hqspi->Init.FifoThreshold));
+ assert_param(IS_QSPI_SSHIFT(hqspi->Init.SampleShifting));
+ assert_param(IS_QSPI_FLASH_SIZE(hqspi->Init.FlashSize));
+ assert_param(IS_QSPI_CS_HIGH_TIME(hqspi->Init.ChipSelectHighTime));
+ assert_param(IS_QSPI_CLOCK_MODE(hqspi->Init.ClockMode));
+ assert_param(IS_QSPI_DUAL_FLASH_MODE(hqspi->Init.DualFlash));
+
+ if (hqspi->Init.DualFlash != QSPI_DUALFLASH_ENABLE )
+ {
+ assert_param(IS_QSPI_FLASH_ID(hqspi->Init.FlashID));
+ }
+
+ if(hqspi->State == HAL_QSPI_STATE_RESET)
+ {
+
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ /* Reset Callback pointers in HAL_QSPI_STATE_RESET only */
+ hqspi->ErrorCallback = HAL_QSPI_ErrorCallback;
+ hqspi->AbortCpltCallback = HAL_QSPI_AbortCpltCallback;
+ hqspi->FifoThresholdCallback = HAL_QSPI_FifoThresholdCallback;
+ hqspi->CmdCpltCallback = HAL_QSPI_CmdCpltCallback;
+ hqspi->RxCpltCallback = HAL_QSPI_RxCpltCallback;
+ hqspi->TxCpltCallback = HAL_QSPI_TxCpltCallback;
+ hqspi->StatusMatchCallback = HAL_QSPI_StatusMatchCallback;
+ hqspi->TimeOutCallback = HAL_QSPI_TimeOutCallback;
+
+ if(hqspi->MspInitCallback == NULL)
+ {
+ hqspi->MspInitCallback = HAL_QSPI_MspInit;
+ }
+
+ /* Init the low level hardware */
+ hqspi->MspInitCallback(hqspi);
+#else
+ /* Init the low level hardware : GPIO, CLOCK */
+ HAL_QSPI_MspInit(hqspi);
+#endif
+
+ /* Configure the default timeout for the QSPI memory access */
+ HAL_QSPI_SetTimeout(hqspi, HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
+ }
+
+ /* Configure QSPI FIFO Threshold */
+ MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES,
+ ((hqspi->Init.FifoThreshold - 1U) << QUADSPI_CR_FTHRES_Pos));
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
+
+ if(status == HAL_OK)
+ {
+ /* Configure QSPI Clock Prescaler and Sample Shift */
+ MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PRESCALER | QUADSPI_CR_SSHIFT | QUADSPI_CR_FSEL | QUADSPI_CR_DFM),
+ ((hqspi->Init.ClockPrescaler << QUADSPI_CR_PRESCALER_Pos) |
+ hqspi->Init.SampleShifting | hqspi->Init.FlashID | hqspi->Init.DualFlash));
+
+ /* Configure QSPI Flash Size, CS High Time and Clock Mode */
+ MODIFY_REG(hqspi->Instance->DCR, (QUADSPI_DCR_FSIZE | QUADSPI_DCR_CSHT | QUADSPI_DCR_CKMODE),
+ ((hqspi->Init.FlashSize << QUADSPI_DCR_FSIZE_Pos) |
+ hqspi->Init.ChipSelectHighTime | hqspi->Init.ClockMode));
+
+ /* Enable the QSPI peripheral */
+ __HAL_QSPI_ENABLE(hqspi);
+
+ /* Set QSPI error code to none */
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Initialize the QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief De-Initialize the QSPI peripheral.
+ * @param hqspi QSPI handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_DeInit(QSPI_HandleTypeDef *hqspi)
+{
+ /* Check the QSPI handle allocation */
+ if(hqspi == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the QSPI Peripheral Clock */
+ __HAL_QSPI_DISABLE(hqspi);
+
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ if(hqspi->MspDeInitCallback == NULL)
+ {
+ hqspi->MspDeInitCallback = HAL_QSPI_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hqspi->MspDeInitCallback(hqspi);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
+ HAL_QSPI_MspDeInit(hqspi);
+#endif
+
+ /* Set QSPI error code to none */
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Initialize the QSPI state */
+ hqspi->State = HAL_QSPI_STATE_RESET;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the QSPI MSP.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_MspInit can be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the QSPI MSP.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_MspDeInit can be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup QSPI_Exported_Functions_Group2 Input and Output operation functions
+ * @brief QSPI Transmit/Receive functions
+ *
+@verbatim
+ ===============================================================================
+ ##### IO operation functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Handle the interrupts.
+ (+) Handle the command sequence.
+ (+) Transmit data in blocking, interrupt or DMA mode.
+ (+) Receive data in blocking, interrupt or DMA mode.
+ (+) Manage the auto-polling functional mode.
+ (+) Manage the memory-mapped functional mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Handle QSPI interrupt request.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+void HAL_QSPI_IRQHandler(QSPI_HandleTypeDef *hqspi)
+{
+ __IO uint32_t *data_reg;
+ uint32_t flag = READ_REG(hqspi->Instance->SR);
+ uint32_t itsource = READ_REG(hqspi->Instance->CR);
+
+ /* QSPI Fifo Threshold interrupt occurred ----------------------------------*/
+ if(((flag & QSPI_FLAG_FT) != 0U) && ((itsource & QSPI_IT_FT) != 0U))
+ {
+ data_reg = &hqspi->Instance->DR;
+
+ if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX)
+ {
+ /* Transmission process */
+ while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != RESET)
+ {
+ if (hqspi->TxXferCount > 0U)
+ {
+ /* Fill the FIFO until the threshold is reached */
+ *((__IO uint8_t *)data_reg) = *hqspi->pTxBuffPtr;
+ hqspi->pTxBuffPtr++;
+ hqspi->TxXferCount--;
+ }
+ else
+ {
+ /* No more data available for the transfer */
+ /* Disable the QSPI FIFO Threshold Interrupt */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT);
+ break;
+ }
+ }
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX)
+ {
+ /* Receiving Process */
+ while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != RESET)
+ {
+ if (hqspi->RxXferCount > 0U)
+ {
+ /* Read the FIFO until the threshold is reached */
+ *hqspi->pRxBuffPtr = *((__IO uint8_t *)data_reg);
+ hqspi->pRxBuffPtr++;
+ hqspi->RxXferCount--;
+ }
+ else
+ {
+ /* All data have been received for the transfer */
+ /* Disable the QSPI FIFO Threshold Interrupt */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+
+ /* FIFO Threshold callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->FifoThresholdCallback(hqspi);
+#else
+ HAL_QSPI_FifoThresholdCallback(hqspi);
+#endif
+ }
+
+ /* QSPI Transfer Complete interrupt occurred -------------------------------*/
+ else if(((flag & QSPI_FLAG_TC) != 0U) && ((itsource & QSPI_IT_TC) != 0U))
+ {
+ /* Clear interrupt */
+ WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TC);
+
+ /* Disable the QSPI FIFO Threshold, Transfer Error and Transfer complete Interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT);
+
+ /* Transfer complete callback */
+ if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX)
+ {
+ if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable using MDMA by clearing DMAEN, note that DMAEN bit is "reserved"
+ but no impact on H7 HW and it minimize the cost in the footprint */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hqspi->hmdma);
+ }
+
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* TX Complete callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->TxCpltCallback(hqspi);
+#else
+ HAL_QSPI_TxCpltCallback(hqspi);
+#endif
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX)
+ {
+ if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable using MDMA by clearing DMAEN, note that DMAEN bit is "reserved"
+ but no impact on H7 HW and it minimize the cost in the footprint */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hqspi->hmdma);
+ }
+ else
+ {
+ data_reg = &hqspi->Instance->DR;
+ while(READ_BIT(hqspi->Instance->SR, QUADSPI_SR_FLEVEL) != 0U)
+ {
+ if (hqspi->RxXferCount > 0U)
+ {
+ /* Read the last data received in the FIFO until it is empty */
+ *hqspi->pRxBuffPtr = *((__IO uint8_t *)data_reg);
+ hqspi->pRxBuffPtr++;
+ hqspi->RxXferCount--;
+ }
+ else
+ {
+ /* All data have been received for the transfer */
+ break;
+ }
+ }
+ }
+
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* RX Complete callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->RxCpltCallback(hqspi);
+#else
+ HAL_QSPI_RxCpltCallback(hqspi);
+#endif
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_BUSY)
+ {
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Command Complete callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->CmdCpltCallback(hqspi);
+#else
+ HAL_QSPI_CmdCpltCallback(hqspi);
+#endif
+ }
+ else if(hqspi->State == HAL_QSPI_STATE_ABORT)
+ {
+ /* Reset functional mode configuration to indirect write mode by default */
+ CLEAR_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FMODE);
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ if (hqspi->ErrorCode == HAL_QSPI_ERROR_NONE)
+ {
+ /* Abort called by the user */
+
+ /* Abort Complete callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->AbortCpltCallback(hqspi);
+#else
+ HAL_QSPI_AbortCpltCallback(hqspi);
+#endif
+ }
+ else
+ {
+ /* Abort due to an error (eg : MDMA error) */
+
+ /* Error callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->ErrorCallback(hqspi);
+#else
+ HAL_QSPI_ErrorCallback(hqspi);
+#endif
+ }
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+
+ /* QSPI Status Match interrupt occurred ------------------------------------*/
+ else if(((flag & QSPI_FLAG_SM) != 0U) && ((itsource & QSPI_IT_SM) != 0U))
+ {
+ /* Clear interrupt */
+ WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_SM);
+
+ /* Check if the automatic poll mode stop is activated */
+ if(READ_BIT(hqspi->Instance->CR, QUADSPI_CR_APMS) != 0U)
+ {
+ /* Disable the QSPI Transfer Error and Status Match Interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE));
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+
+ /* Status match callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->StatusMatchCallback(hqspi);
+#else
+ HAL_QSPI_StatusMatchCallback(hqspi);
+#endif
+ }
+
+ /* QSPI Transfer Error interrupt occurred ----------------------------------*/
+ else if(((flag & QSPI_FLAG_TE) != 0U) && ((itsource & QSPI_IT_TE) != 0U))
+ {
+ /* Clear interrupt */
+ WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TE);
+
+ /* Disable all the QSPI Interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_SM | QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT);
+
+ /* Set error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_TRANSFER;
+
+ if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable using MDMA by clearing DMAEN, note that DMAEN bit is "reserved"
+ but no impact on H7 HW and it minimize the cost in the footprint */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Disable the MDMA channel */
+ hqspi->hmdma->XferAbortCallback = QSPI_DMAAbortCplt;
+ if (HAL_MDMA_Abort_IT(hqspi->hmdma) != HAL_OK)
+ {
+ /* Set error code to DMA */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Error callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->ErrorCallback(hqspi);
+#else
+ HAL_QSPI_ErrorCallback(hqspi);
+#endif
+ }
+ }
+ else
+ {
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Error callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->ErrorCallback(hqspi);
+#else
+ HAL_QSPI_ErrorCallback(hqspi);
+#endif
+ }
+ }
+
+ /* QSPI Timeout interrupt occurred -----------------------------------------*/
+ else if(((flag & QSPI_FLAG_TO) != 0U) && ((itsource & QSPI_IT_TO) != 0U))
+ {
+ /* Clear interrupt */
+ WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TO);
+
+ /* Timeout callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->TimeOutCallback(hqspi);
+#else
+ HAL_QSPI_TimeOutCallback(hqspi);
+#endif
+ }
+
+ else
+ {
+ /* Nothing to do */
+ }
+}
+
+/**
+ * @brief Set the command configuration.
+ * @param hqspi QSPI handle
+ * @param cmd : structure that contains the command configuration information
+ * @param Timeout Timeout duration
+ * @note This function is used only in Indirect Read or Write Modes
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Command(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_BUSY;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Call the configuration function */
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ if (cmd->DataMode == QSPI_DATA_NONE)
+ {
+ /* When there is no data phase, the transfer start as soon as the configuration is done
+ so wait until TC flag is set to go back in idle state */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ else
+ {
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Set the command configuration in interrupt mode.
+ * @param hqspi QSPI handle
+ * @param cmd structure that contains the command configuration information
+ * @note This function is used only in Indirect Read or Write Modes
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Command_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_BUSY;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ if (cmd->DataMode == QSPI_DATA_NONE)
+ {
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC);
+ }
+
+ /* Call the configuration function */
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ if (cmd->DataMode == QSPI_DATA_NONE)
+ {
+ /* When there is no data phase, the transfer start as soon as the configuration is done
+ so activate TC and TE interrupts */
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Enable the QSPI Transfer Error Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_TC);
+ }
+ else
+ {
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hqspi QSPI handle
+ * @param pData pointer to data buffer
+ * @param Timeout Timeout duration
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Transmit(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart = HAL_GetTick();
+ __IO uint32_t *data_reg = &hqspi->Instance->DR;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ if(pData != NULL )
+ {
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX;
+
+ /* Configure counters and size of the handle */
+ hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->pTxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional as indirect write */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ while(hqspi->TxXferCount > 0U)
+ {
+ /* Wait until FT flag is set to send data */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_FT, SET, tickstart, Timeout);
+
+ if (status != HAL_OK)
+ {
+ break;
+ }
+
+ *((__IO uint8_t *)data_reg) = *hqspi->pTxBuffPtr;
+ hqspi->pTxBuffPtr++;
+ hqspi->TxXferCount--;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Wait until TC flag is set to go back in idle state */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Clear Transfer Complete bit */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ }
+ }
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ else
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hqspi QSPI handle
+ * @param pData pointer to data buffer
+ * @param Timeout Timeout duration
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Receive(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t addr_reg = READ_REG(hqspi->Instance->AR);
+ __IO uint32_t *data_reg = &hqspi->Instance->DR;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ if(pData != NULL )
+ {
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX;
+
+ /* Configure counters and size of the handle */
+ hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->pRxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional as indirect read */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Start the transfer by re-writing the address in AR register */
+ WRITE_REG(hqspi->Instance->AR, addr_reg);
+
+ while(hqspi->RxXferCount > 0U)
+ {
+ /* Wait until FT or TC flag is set to read received data */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, (QSPI_FLAG_FT | QSPI_FLAG_TC), SET, tickstart, Timeout);
+
+ if (status != HAL_OK)
+ {
+ break;
+ }
+
+ *hqspi->pRxBuffPtr = *((__IO uint8_t *)data_reg);
+ hqspi->pRxBuffPtr++;
+ hqspi->RxXferCount--;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Wait until TC flag is set to go back in idle state */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Clear Transfer Complete bit */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ }
+ }
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ else
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM;
+ status = HAL_ERROR;
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ return status;
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode with interrupt.
+ * @param hqspi QSPI handle
+ * @param pData pointer to data buffer
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Transmit_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ if(pData != NULL )
+ {
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX;
+
+ /* Configure counters and size of the handle */
+ hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->pTxBuffPtr = pData;
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC);
+
+ /* Configure QSPI: CCR register with functional as indirect write */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC);
+ }
+ else
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM;
+ status = HAL_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with interrupt.
+ * @param hqspi QSPI handle
+ * @param pData pointer to data buffer
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Receive_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t addr_reg = READ_REG(hqspi->Instance->AR);
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ if(pData != NULL )
+ {
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX;
+
+ /* Configure counters and size of the handle */
+ hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1U;
+ hqspi->pRxBuffPtr = pData;
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC);
+
+ /* Configure QSPI: CCR register with functional as indirect read */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Start the transfer by re-writing the address in AR register */
+ WRITE_REG(hqspi->Instance->AR, addr_reg);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC);
+ }
+ else
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM;
+ status = HAL_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Send an amount of data in non-blocking mode with DMA.
+ * @param hqspi QSPI handle
+ * @param pData pointer to data buffer
+ * @note This function is used only in Indirect Write Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Transmit_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t data_size = (READ_REG(hqspi->Instance->DLR) + 1U);
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ /* Clear the error code */
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ if(pData != NULL )
+ {
+ /* Configure counters of the handle */
+ hqspi->TxXferCount = data_size;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX;
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, (QSPI_FLAG_TE | QSPI_FLAG_TC));
+
+ /* Configure size and pointer of the handle */
+ hqspi->TxXferSize = hqspi->TxXferCount;
+ hqspi->pTxBuffPtr = pData;
+
+ /* Configure QSPI: CCR register with functional mode as indirect write */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
+
+ /* Set the QSPI MDMA transfer complete callback */
+ hqspi->hmdma->XferCpltCallback = QSPI_DMATxCplt;
+
+ /* Set the MDMA error callback */
+ hqspi->hmdma->XferErrorCallback = QSPI_DMAError;
+
+ /* Clear the MDMA abort callback */
+ hqspi->hmdma->XferAbortCallback = NULL;
+
+ /* In Transmit mode , the MDMA destination is the QSPI DR register : Force the MDMA Destination Increment to disable */
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) ,MDMA_DEST_INC_DISABLE);
+
+ /* Update MDMA configuration with the correct SourceInc field for Write operation */
+ if (hqspi->hmdma->Init.SourceDataSize == MDMA_SRC_DATASIZE_BYTE)
+ {
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_BYTE);
+ }
+ else if (hqspi->hmdma->Init.SourceDataSize == MDMA_SRC_DATASIZE_HALFWORD)
+ {
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_HALFWORD);
+ }
+ else if (hqspi->hmdma->Init.SourceDataSize == MDMA_SRC_DATASIZE_WORD)
+ {
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_WORD);
+ }
+ else
+ {
+ /* in case of incorrect source data size */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+ status = HAL_ERROR;
+ }
+
+ /* Enable the QSPI transfer error Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE);
+
+ /* Use DMAEN bit with no impact on H7 HW to record MDMA transfer request */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+
+ /* Enable the QSPI transmit MDMA */
+ if (HAL_MDMA_Start_IT(hqspi->hmdma, (uint32_t)pData, (uint32_t)&hqspi->Instance->DR, hqspi->TxXferSize, 1) == HAL_OK)
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ else
+ {
+ /* Clear DMAEN bit with no impact on H7 HW to cancel MDMA transfer request */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ status = HAL_ERROR;
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM;
+ status = HAL_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @param hqspi QSPI handle
+ * @param pData pointer to data buffer.
+ * @note This function is used only in Indirect Read Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_Receive_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t addr_reg = READ_REG(hqspi->Instance->AR);
+ uint32_t data_size = (READ_REG(hqspi->Instance->DLR) + 1U);
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ /* Clear the error code */
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ if(pData != NULL )
+ {
+ /* Configure counters of the handle */
+ hqspi->RxXferCount = data_size;
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX;
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, (QSPI_FLAG_TE | QSPI_FLAG_TC));
+
+ /* Configure size and pointer of the handle */
+ hqspi->RxXferSize = hqspi->RxXferCount;
+ hqspi->pRxBuffPtr = pData;
+
+ /* Set the QSPI MDMA transfer complete callback */
+ hqspi->hmdma->XferCpltCallback = QSPI_DMARxCplt;
+
+ /* Set the MDMA error callback */
+ hqspi->hmdma->XferErrorCallback = QSPI_DMAError;
+
+ /* Clear the MDMA abort callback */
+ hqspi->hmdma->XferAbortCallback = NULL;
+
+ /* In Receive mode , the MDMA source is the QSPI DR register : Force the MDMA Source Increment to disable */
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_SINC | MDMA_CTCR_SINCOS) , MDMA_SRC_INC_DISABLE);
+
+ /* Update MDMA configuration with the correct DestinationInc field for read operation */
+ if (hqspi->hmdma->Init.DestDataSize == MDMA_DEST_DATASIZE_BYTE)
+ {
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) , MDMA_DEST_INC_BYTE);
+ }
+ else if (hqspi->hmdma->Init.DestDataSize == MDMA_DEST_DATASIZE_HALFWORD)
+ {
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) , MDMA_DEST_INC_HALFWORD);
+ }
+ else if (hqspi->hmdma->Init.DestDataSize == MDMA_DEST_DATASIZE_WORD)
+ {
+ MODIFY_REG(hqspi->hmdma->Instance->CTCR, (MDMA_CTCR_DINC | MDMA_CTCR_DINCOS) , MDMA_DEST_INC_WORD);
+ }
+ else
+ {
+ /* in case of incorrect destination data size */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+ status = HAL_ERROR;
+ }
+ /* Configure QSPI: CCR register with functional as indirect read */
+ MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ);
+
+ /* Start the transfer by re-writing the address in AR register */
+ WRITE_REG(hqspi->Instance->AR, addr_reg);
+
+ /* Enable the QSPI transfer error Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE);
+
+ /* Use DMAEN bit with no impact on H7 HW to record MDMA transfer request */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Enable the MDMA */
+ if (HAL_MDMA_Start_IT(hqspi->hmdma, (uint32_t)&hqspi->Instance->DR, (uint32_t)pData, hqspi->RxXferSize, 1) == HAL_OK)
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ else
+ {
+ /* Clear DMAEN bit with no impact on H7 HW to cancel MDMA transfer request */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ status = HAL_ERROR;
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM;
+ status = HAL_ERROR;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Configure the QSPI Automatic Polling Mode in blocking mode.
+ * @param hqspi QSPI handle
+ * @param cmd structure that contains the command configuration information.
+ * @param cfg structure that contains the polling configuration information.
+ * @param Timeout Timeout duration
+ * @note This function is used only in Automatic Polling Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_AutoPolling(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg, uint32_t Timeout)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ assert_param(IS_QSPI_INTERVAL(cfg->Interval));
+ assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize));
+ assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure QSPI: PSMAR register with the status match value */
+ WRITE_REG(hqspi->Instance->PSMAR, cfg->Match);
+
+ /* Configure QSPI: PSMKR register with the status mask value */
+ WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask);
+
+ /* Configure QSPI: PIR register with the interval value */
+ WRITE_REG(hqspi->Instance->PIR, cfg->Interval);
+
+ /* Configure QSPI: CR register with Match mode and Automatic stop enabled
+ (otherwise there will be an infinite loop in blocking mode) */
+ MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS),
+ (cfg->MatchMode | QSPI_AUTOMATIC_STOP_ENABLE));
+
+ /* Call the configuration function */
+ cmd->NbData = cfg->StatusBytesSize;
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING);
+
+ /* Wait until SM flag is set to go back in idle state */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_SM, SET, tickstart, Timeout);
+
+ if (status == HAL_OK)
+ {
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_SM);
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the QSPI Automatic Polling Mode in non-blocking mode.
+ * @param hqspi QSPI handle
+ * @param cmd structure that contains the command configuration information.
+ * @param cfg structure that contains the polling configuration information.
+ * @note This function is used only in Automatic Polling Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_AutoPolling_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ assert_param(IS_QSPI_INTERVAL(cfg->Interval));
+ assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize));
+ assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode));
+ assert_param(IS_QSPI_AUTOMATIC_STOP(cfg->AutomaticStop));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure QSPI: PSMAR register with the status match value */
+ WRITE_REG(hqspi->Instance->PSMAR, cfg->Match);
+
+ /* Configure QSPI: PSMKR register with the status mask value */
+ WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask);
+
+ /* Configure QSPI: PIR register with the interval value */
+ WRITE_REG(hqspi->Instance->PIR, cfg->Interval);
+
+ /* Configure QSPI: CR register with Match mode and Automatic stop mode */
+ MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS),
+ (cfg->MatchMode | cfg->AutomaticStop));
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_SM);
+
+ /* Call the configuration function */
+ cmd->NbData = cfg->StatusBytesSize;
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Enable the QSPI Transfer Error and status match Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE));
+
+ }
+ else
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the Memory Mapped mode.
+ * @param hqspi QSPI handle
+ * @param cmd structure that contains the command configuration information.
+ * @param cfg structure that contains the memory mapped configuration information.
+ * @note This function is used only in Memory mapped Mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_MemoryMapped(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_MemoryMappedTypeDef *cfg)
+{
+ HAL_StatusTypeDef status;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check the parameters */
+ assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode));
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction));
+ }
+
+ assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode));
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize));
+ }
+
+ assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode));
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize));
+ }
+
+ assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles));
+ assert_param(IS_QSPI_DATA_MODE(cmd->DataMode));
+
+ assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode));
+ assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle));
+ assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode));
+
+ assert_param(IS_QSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ hqspi->ErrorCode = HAL_QSPI_ERROR_NONE;
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_BUSY_MEM_MAPPED;
+
+ /* Wait till BUSY flag reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ /* Configure QSPI: CR register with timeout counter enable */
+ MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_TCEN, cfg->TimeOutActivation);
+
+ if (cfg->TimeOutActivation == QSPI_TIMEOUT_COUNTER_ENABLE)
+ {
+ assert_param(IS_QSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod));
+
+ /* Configure QSPI: LPTR register with the low-power timeout value */
+ WRITE_REG(hqspi->Instance->LPTR, cfg->TimeOutPeriod);
+
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TO);
+
+ /* Enable the QSPI TimeOut Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TO);
+ }
+
+ /* Call the configuration function */
+ QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED);
+ }
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Transfer Error callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_ErrorCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Abort completed callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_AbortCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_AbortCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Command completed callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_CmdCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_TxCpltCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE: This function should not be modified, when the callback is needed,
+ the HAL_QSPI_TxCpltCallback could be implemented in the user file
+ */
+}
+
+
+/**
+ * @brief FIFO Threshold callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_FifoThresholdCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_FIFOThresholdCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Status Match callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_StatusMatchCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Timeout callback.
+ * @param hqspi QSPI handle
+ * @retval None
+ */
+__weak void HAL_QSPI_TimeOutCallback(QSPI_HandleTypeDef *hqspi)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hqspi);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_QSPI_TimeOutCallback could be implemented in the user file
+ */
+}
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User QSPI Callback
+ * To be used to override the weak predefined callback
+ * @param hqspi QSPI handle
+ * @param CallbackId ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_QSPI_ERROR_CB_ID QSPI Error Callback ID
+ * @arg @ref HAL_QSPI_ABORT_CB_ID QSPI Abort Callback ID
+ * @arg @ref HAL_QSPI_FIFO_THRESHOLD_CB_ID QSPI FIFO Threshold Callback ID
+ * @arg @ref HAL_QSPI_CMD_CPLT_CB_ID QSPI Command Complete Callback ID
+ * @arg @ref HAL_QSPI_RX_CPLT_CB_ID QSPI Rx Complete Callback ID
+ * @arg @ref HAL_QSPI_TX_CPLT_CB_ID QSPI Tx Complete Callback ID
+ * @arg @ref HAL_QSPI_STATUS_MATCH_CB_ID QSPI Status Match Callback ID
+ * @arg @ref HAL_QSPI_TIMEOUT_CB_ID QSPI Timeout Callback ID
+ * @arg @ref HAL_QSPI_MSP_INIT_CB_ID QSPI MspInit callback ID
+ * @arg @ref HAL_QSPI_MSP_DEINIT_CB_ID QSPI MspDeInit callback ID
+ * @param pCallback pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_QSPI_RegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId, pQSPI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if(pCallback == NULL)
+ {
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_QSPI_ERROR_CB_ID :
+ hqspi->ErrorCallback = pCallback;
+ break;
+ case HAL_QSPI_ABORT_CB_ID :
+ hqspi->AbortCpltCallback = pCallback;
+ break;
+ case HAL_QSPI_FIFO_THRESHOLD_CB_ID :
+ hqspi->FifoThresholdCallback = pCallback;
+ break;
+ case HAL_QSPI_CMD_CPLT_CB_ID :
+ hqspi->CmdCpltCallback = pCallback;
+ break;
+ case HAL_QSPI_RX_CPLT_CB_ID :
+ hqspi->RxCpltCallback = pCallback;
+ break;
+ case HAL_QSPI_TX_CPLT_CB_ID :
+ hqspi->TxCpltCallback = pCallback;
+ break;
+ case HAL_QSPI_STATUS_MATCH_CB_ID :
+ hqspi->StatusMatchCallback = pCallback;
+ break;
+ case HAL_QSPI_TIMEOUT_CB_ID :
+ hqspi->TimeOutCallback = pCallback;
+ break;
+ case HAL_QSPI_MSP_INIT_CB_ID :
+ hqspi->MspInitCallback = pCallback;
+ break;
+ case HAL_QSPI_MSP_DEINIT_CB_ID :
+ hqspi->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hqspi->State == HAL_QSPI_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_QSPI_MSP_INIT_CB_ID :
+ hqspi->MspInitCallback = pCallback;
+ break;
+ case HAL_QSPI_MSP_DEINIT_CB_ID :
+ hqspi->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hqspi);
+ return status;
+}
+
+/**
+ * @brief Unregister a User QSPI Callback
+ * QSPI Callback is redirected to the weak predefined callback
+ * @param hqspi QSPI handle
+ * @param CallbackId ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_QSPI_ERROR_CB_ID QSPI Error Callback ID
+ * @arg @ref HAL_QSPI_ABORT_CB_ID QSPI Abort Callback ID
+ * @arg @ref HAL_QSPI_FIFO_THRESHOLD_CB_ID QSPI FIFO Threshold Callback ID
+ * @arg @ref HAL_QSPI_CMD_CPLT_CB_ID QSPI Command Complete Callback ID
+ * @arg @ref HAL_QSPI_RX_CPLT_CB_ID QSPI Rx Complete Callback ID
+ * @arg @ref HAL_QSPI_TX_CPLT_CB_ID QSPI Tx Complete Callback ID
+ * @arg @ref HAL_QSPI_STATUS_MATCH_CB_ID QSPI Status Match Callback ID
+ * @arg @ref HAL_QSPI_TIMEOUT_CB_ID QSPI Timeout Callback ID
+ * @arg @ref HAL_QSPI_MSP_INIT_CB_ID QSPI MspInit callback ID
+ * @arg @ref HAL_QSPI_MSP_DEINIT_CB_ID QSPI MspDeInit callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_QSPI_UnRegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ switch (CallbackId)
+ {
+ case HAL_QSPI_ERROR_CB_ID :
+ hqspi->ErrorCallback = HAL_QSPI_ErrorCallback;
+ break;
+ case HAL_QSPI_ABORT_CB_ID :
+ hqspi->AbortCpltCallback = HAL_QSPI_AbortCpltCallback;
+ break;
+ case HAL_QSPI_FIFO_THRESHOLD_CB_ID :
+ hqspi->FifoThresholdCallback = HAL_QSPI_FifoThresholdCallback;
+ break;
+ case HAL_QSPI_CMD_CPLT_CB_ID :
+ hqspi->CmdCpltCallback = HAL_QSPI_CmdCpltCallback;
+ break;
+ case HAL_QSPI_RX_CPLT_CB_ID :
+ hqspi->RxCpltCallback = HAL_QSPI_RxCpltCallback;
+ break;
+ case HAL_QSPI_TX_CPLT_CB_ID :
+ hqspi->TxCpltCallback = HAL_QSPI_TxCpltCallback;
+ break;
+ case HAL_QSPI_STATUS_MATCH_CB_ID :
+ hqspi->StatusMatchCallback = HAL_QSPI_StatusMatchCallback;
+ break;
+ case HAL_QSPI_TIMEOUT_CB_ID :
+ hqspi->TimeOutCallback = HAL_QSPI_TimeOutCallback;
+ break;
+ case HAL_QSPI_MSP_INIT_CB_ID :
+ hqspi->MspInitCallback = HAL_QSPI_MspInit;
+ break;
+ case HAL_QSPI_MSP_DEINIT_CB_ID :
+ hqspi->MspDeInitCallback = HAL_QSPI_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hqspi->State == HAL_QSPI_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_QSPI_MSP_INIT_CB_ID :
+ hqspi->MspInitCallback = HAL_QSPI_MspInit;
+ break;
+ case HAL_QSPI_MSP_DEINIT_CB_ID :
+ hqspi->MspDeInitCallback = HAL_QSPI_MspDeInit;
+ break;
+ default :
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Update the error code */
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hqspi);
+ return status;
+}
+#endif
+
+/**
+ * @}
+ */
+
+/** @defgroup QSPI_Exported_Functions_Group3 Peripheral Control and State functions
+ * @brief QSPI control and State functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Peripheral Control and State functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to :
+ (+) Check in run-time the state of the driver.
+ (+) Check the error code set during last operation.
+ (+) Abort any operation.
+
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the QSPI handle state.
+ * @param hqspi QSPI handle
+ * @retval HAL state
+ */
+HAL_QSPI_StateTypeDef HAL_QSPI_GetState(const QSPI_HandleTypeDef *hqspi)
+{
+ /* Return QSPI handle state */
+ return hqspi->State;
+}
+
+/**
+* @brief Return the QSPI error code.
+* @param hqspi QSPI handle
+* @retval QSPI Error Code
+*/
+uint32_t HAL_QSPI_GetError(const QSPI_HandleTypeDef *hqspi)
+{
+ return hqspi->ErrorCode;
+}
+
+/**
+* @brief Abort the current transmission.
+* @param hqspi QSPI handle
+* @retval HAL status
+*/
+HAL_StatusTypeDef HAL_QSPI_Abort(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart = HAL_GetTick();
+
+ /* Check if the state is in one of the busy states */
+ if (((uint32_t)hqspi->State & 0x2U) != 0U)
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable using MDMA by clearing DMAEN, note that DMAEN bit is "reserved"
+ but no impact on H7 HW and it minimize the cost in the footprint */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Abort MDMA */
+ status = HAL_MDMA_Abort(hqspi->hmdma);
+ if(status != HAL_OK)
+ {
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+ }
+ }
+
+ if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_BUSY) != RESET)
+ {
+ /* Configure QSPI: CR register with Abort request */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT);
+
+ /* Wait until TC flag is set to go back in idle state */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, hqspi->Timeout);
+
+ if (status == HAL_OK)
+ {
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Wait until BUSY flag is reset */
+ status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout);
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Reset functional mode configuration to indirect write mode by default */
+ CLEAR_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FMODE);
+
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ else
+ {
+ /* Update state */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+
+ return status;
+}
+
+/**
+* @brief Abort the current transmission (non-blocking function)
+* @param hqspi QSPI handle
+* @retval HAL status
+*/
+HAL_StatusTypeDef HAL_QSPI_Abort_IT(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check if the state is in one of the busy states */
+ if (((uint32_t)hqspi->State & 0x2U) != 0U)
+ {
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Update QSPI state */
+ hqspi->State = HAL_QSPI_STATE_ABORT;
+
+ /* Disable all interrupts */
+ __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_TO | QSPI_IT_SM | QSPI_IT_FT | QSPI_IT_TC | QSPI_IT_TE));
+
+ if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U)
+ {
+ /* Disable using MDMA by clearing DMAEN, note that DMAEN bit is "reserved"
+ but no impact on H7 HW and it minimize the cost in the footprint */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Abort MDMA channel */
+ hqspi->hmdma->XferAbortCallback = QSPI_DMAAbortCplt;
+ if (HAL_MDMA_Abort_IT(hqspi->hmdma) != HAL_OK)
+ {
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Abort Complete callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->AbortCpltCallback(hqspi);
+#else
+ HAL_QSPI_AbortCpltCallback(hqspi);
+#endif
+ }
+ }
+ else
+ {
+ if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_BUSY) != RESET)
+ {
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Enable the QSPI Transfer Complete Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC);
+
+ /* Configure QSPI: CR register with Abort request */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT);
+ }
+ else
+ {
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+ }
+ }
+ }
+ return status;
+}
+
+/** @brief Set QSPI timeout.
+ * @param hqspi QSPI handle.
+ * @param Timeout Timeout for the QSPI memory access.
+ * @retval None
+ */
+void HAL_QSPI_SetTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Timeout)
+{
+ hqspi->Timeout = Timeout;
+}
+
+/** @brief Set QSPI Fifo threshold.
+ * @param hqspi QSPI handle.
+ * @param Threshold Threshold of the Fifo (value between 1 and 16).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_SetFifoThreshold(QSPI_HandleTypeDef *hqspi, uint32_t Threshold)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ /* Synchronize init structure with new FIFO threshold value */
+ hqspi->Init.FifoThreshold = Threshold;
+
+ /* Configure QSPI FIFO Threshold */
+ MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES,
+ ((hqspi->Init.FifoThreshold - 1U) << QUADSPI_CR_FTHRES_Pos));
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/** @brief Get QSPI Fifo threshold.
+ * @param hqspi QSPI handle.
+ * @retval Fifo threshold (value between 1 and 16)
+ */
+uint32_t HAL_QSPI_GetFifoThreshold(const QSPI_HandleTypeDef *hqspi)
+{
+ return ((READ_BIT(hqspi->Instance->CR, QUADSPI_CR_FTHRES) >> QUADSPI_CR_FTHRES_Pos) + 1U);
+}
+
+/** @brief Set FlashID.
+ * @param hqspi QSPI handle.
+ * @param FlashID Index of the flash memory to be accessed.
+ * This parameter can be a value of @ref QSPI_Flash_Select.
+ * @note The FlashID is ignored when dual flash mode is enabled.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_SetFlashID(QSPI_HandleTypeDef *hqspi, uint32_t FlashID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameter */
+ assert_param(IS_QSPI_FLASH_ID(FlashID));
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if(hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ /* Synchronize init structure with new FlashID value */
+ hqspi->Init.FlashID = FlashID;
+
+ /* Configure QSPI FlashID */
+ MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FSEL, FlashID);
+ }
+ else
+ {
+ status = HAL_BUSY;
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+#if defined(QUADSPI_CCR_FRCM)
+/** @brief Enable Free Running Clock Mode.
+ * @param hqspi QSPI handle.
+ * @note Free running clock mode could only be enabled when BUSY = 0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_EnableFreeRunningClockMode(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if (hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_BUSY) == RESET)
+ {
+ /* Enable Free Running Clock mode */
+ SET_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FRCM);
+ status = HAL_OK;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/** @brief Disable Free Running Clock Mode.
+ * @param hqspi QSPI handle.
+ * @note Free running clock mode could only be disabled when BUSY = 0.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_QSPI_DisableFreeRunningClockMode(QSPI_HandleTypeDef *hqspi)
+{
+ HAL_StatusTypeDef status = HAL_BUSY;
+
+ /* Process locked */
+ __HAL_LOCK(hqspi);
+
+ if (hqspi->State == HAL_QSPI_STATE_READY)
+ {
+ if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_BUSY) == RESET)
+ {
+ /* Disable Free Running Clock mode */
+ CLEAR_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FRCM);
+ status = HAL_OK;
+ }
+ }
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hqspi);
+
+ /* Return function status */
+ return status;
+}
+
+/** @brief Inidicate if Free Running Clock Mode is enabled.
+ * @param hqspi QSPI handle.
+ * @retval Free Running Clock Mode status (0 : Normal mode, 1 : Free running clock mode)
+ */
+uint32_t HAL_QSPI_IsEnabledFreeRunningClockMode(QSPI_HandleTypeDef *hqspi)
+{
+ return (READ_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FRCM) >> QUADSPI_CCR_FRCM_Pos);
+}
+
+#endif /* QUADSPI_CCR_FRCM */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup QSPI_Private_Functions QSPI Private Functions
+ * @{
+ */
+
+/**
+ * @brief DMA QSPI receive process complete callback.
+ * @param hmdma MDMA handle
+ * @retval None
+ */
+static void QSPI_DMARxCplt(MDMA_HandleTypeDef *hmdma)
+{
+ QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)(hmdma->Parent);
+ hqspi->RxXferCount = 0U;
+
+ /* Enable the QSPI transfer complete Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC);
+}
+
+/**
+ * @brief DMA QSPI transmit process complete callback.
+ * @param hmdma MDMA handle
+ * @retval None
+ */
+static void QSPI_DMATxCplt(MDMA_HandleTypeDef *hmdma)
+{
+ QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)(hmdma->Parent);
+ hqspi->TxXferCount = 0U;
+
+ /* Enable the QSPI transfer complete Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC);
+}
+
+/**
+ * @brief DMA QSPI communication error callback.
+ * @param hmdma MDMA handle
+ * @retval None
+ */
+static void QSPI_DMAError(MDMA_HandleTypeDef *hmdma)
+{
+ QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )(hmdma->Parent);
+
+ hqspi->RxXferCount = 0U;
+ hqspi->TxXferCount = 0U;
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA;
+
+ /* Disable using MDMA by clearing DMAEN, note that DMAEN bit is "reserved"
+ but no impact on H7 HW and it minimize the cost in the footprint */
+ CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN);
+
+ /* Abort the QSPI */
+ (void)HAL_QSPI_Abort_IT(hqspi);
+
+}
+
+/**
+ * @brief MDMA QSPI abort complete callback.
+ * @param hmdma MDMA handle
+ * @retval None
+ */
+static void QSPI_DMAAbortCplt(MDMA_HandleTypeDef *hmdma)
+{
+ QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )(hmdma->Parent);
+
+ hqspi->RxXferCount = 0U;
+ hqspi->TxXferCount = 0U;
+
+ if(hqspi->State == HAL_QSPI_STATE_ABORT)
+ {
+ /* MDMA Abort called by QSPI abort */
+ /* Clear interrupt */
+ __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC);
+
+ /* Enable the QSPI Transfer Complete Interrupt */
+ __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC);
+
+ /* Configure QSPI: CR register with Abort request */
+ SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT);
+ }
+ else
+ {
+ /* MDMA Abort called due to a transfer error interrupt */
+ /* Change state of QSPI */
+ hqspi->State = HAL_QSPI_STATE_READY;
+
+ /* Error callback */
+#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
+ hqspi->ErrorCallback(hqspi);
+#else
+ HAL_QSPI_ErrorCallback(hqspi);
+#endif
+ }
+}
+
+/**
+ * @brief Wait for a flag state until timeout.
+ * @param hqspi QSPI handle
+ * @param Flag Flag checked
+ * @param State Value of the flag expected
+ * @param Tickstart Tick start value
+ * @param Timeout Duration of the timeout
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Flag,
+ FlagStatus State, uint32_t Tickstart, uint32_t Timeout)
+{
+ /* Wait until flag is in expected state */
+ while((__HAL_QSPI_GET_FLAG(hqspi, Flag)) != State)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if(((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
+ {
+ hqspi->State = HAL_QSPI_STATE_ERROR;
+ hqspi->ErrorCode |= HAL_QSPI_ERROR_TIMEOUT;
+
+ return HAL_ERROR;
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the communication registers.
+ * @param hqspi QSPI handle
+ * @param cmd structure that contains the command configuration information
+ * @param FunctionalMode functional mode to configured
+ * This parameter can be one of the following values:
+ * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE: Indirect write mode
+ * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_READ: Indirect read mode
+ * @arg QSPI_FUNCTIONAL_MODE_AUTO_POLLING: Automatic polling mode
+ * @arg QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED: Memory-mapped mode
+ * @retval None
+ */
+static void QSPI_Config(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t FunctionalMode)
+{
+ assert_param(IS_QSPI_FUNCTIONAL_MODE(FunctionalMode));
+
+ if ((cmd->DataMode != QSPI_DATA_NONE) && (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED))
+ {
+ /* Configure QSPI: DLR register with the number of data to read or write */
+ WRITE_REG(hqspi->Instance->DLR, (cmd->NbData - 1U));
+ }
+
+ if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE)
+ {
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ /* Configure QSPI: ABR register with alternate bytes value */
+ WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes);
+
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with instruction, address and alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressSize | cmd->AddressMode | cmd->InstructionMode |
+ cmd->Instruction | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with instruction and alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressMode | cmd->InstructionMode |
+ cmd->Instruction | FunctionalMode));
+
+ /* Clear AR register */
+ CLEAR_REG(hqspi->Instance->AR);
+ }
+ }
+ else
+ {
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with instruction and address ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateByteMode | cmd->AddressSize | cmd->AddressMode |
+ cmd->InstructionMode | cmd->Instruction | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with only instruction ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateByteMode | cmd->AddressMode |
+ cmd->InstructionMode | cmd->Instruction | FunctionalMode));
+
+ /* Clear AR register */
+ CLEAR_REG(hqspi->Instance->AR);
+ }
+ }
+ }
+ else
+ {
+ if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE)
+ {
+ /* Configure QSPI: ABR register with alternate bytes value */
+ WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes);
+
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with address and alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressSize | cmd->AddressMode |
+ cmd->InstructionMode | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with only alternate bytes ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateBytesSize | cmd->AlternateByteMode |
+ cmd->AddressMode | cmd->InstructionMode | FunctionalMode));
+
+ /* Clear AR register */
+ CLEAR_REG(hqspi->Instance->AR);
+ }
+ }
+ else
+ {
+ if (cmd->AddressMode != QSPI_ADDRESS_NONE)
+ {
+ /*---- Command with only address ----*/
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateByteMode | cmd->AddressSize |
+ cmd->AddressMode | cmd->InstructionMode | FunctionalMode));
+
+ if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)
+ {
+ /* Configure QSPI: AR register with address value */
+ WRITE_REG(hqspi->Instance->AR, cmd->Address);
+ }
+ }
+ else
+ {
+ /*---- Command with only data phase ----*/
+ if (cmd->DataMode != QSPI_DATA_NONE)
+ {
+ /* Configure QSPI: CCR register with all communications parameters */
+ WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode |
+ cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) |
+ cmd->AlternateByteMode | cmd->AddressMode |
+ cmd->InstructionMode | FunctionalMode));
+
+ /* Clear AR register */
+ CLEAR_REG(hqspi->Instance->AR);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_QSPI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* defined(QUADSPI) */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
new file mode 100755
index 0000000..1986c78
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc.c
@@ -0,0 +1,1814 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_rcc.c
+ * @author MCD Application Team
+ * @brief RCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Reset and Clock Control (RCC) peripheral:
+ * + Initialization and de-initialization functions
+ * + Peripheral Control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### RCC specific features #####
+ ==============================================================================
+ [..]
+ After reset the device is running from Internal High Speed oscillator
+ (HSI 64MHz) with Flash 0 wait state,and all peripherals are off except
+ internal SRAM, Flash, JTAG and PWR
+ (+) There is no pre-scaler on High speed (AHB) and Low speed (APB) buses;
+ all peripherals mapped on these buses are running at HSI speed.
+ (+) The clock for all peripherals is switched off, except the SRAM and FLASH.
+ (+) All GPIOs are in analogue mode , except the JTAG pins which
+ are assigned to be used for debug purpose.
+
+ [..]
+ Once the device started from reset, the user application has to:
+ (+) Configure the clock source to be used to drive the System clock
+ (if the application needs higher frequency/performance)
+ (+) Configure the System clock frequency and Flash settings
+ (+) Configure the AHB and APB buses pre-scalers
+ (+) Enable the clock for the peripheral(s) to be used
+ (+) Configure the clock kernel source(s) for peripherals which clocks are not
+ derived from the System clock through :RCC_D1CCIPR,RCC_D2CCIP1R,RCC_D2CCIP2R
+ and RCC_D3CCIPR registers
+
+ ##### 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
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file in
+ * the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_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
+ * @{
+ */
+
+/**
+ * @}
+ */
+/* 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,CSI, LSI,HSI48, PLL, CSS and MCO) and the System buses clocks (SYSCLK, AHB3, AHB1
+ AHB2,AHB4,APB3, APB1L, APB1H, APB2, and APB4).
+
+ [..] Internal/external clock and PLL configuration
+ (#) HSI (high-speed internal), 64 MHz factory-trimmed RC used directly or through
+ the PLL as System clock source.
+ (#) CSI is a low-power RC oscillator which can be used directly as system clock, peripheral
+ clock, or PLL input.But even with frequency calibration, is less accurate than an
+ external crystal oscillator or ceramic resonator.
+ (#) LSI (low-speed internal), 32 KHz low consumption RC used as IWDG and/or RTC
+ clock source.
+
+ (#) HSE (high-speed external), 4 to 48 MHz crystal oscillator used directly or
+ through the PLL as System clock source. Can be used also as RTC clock source.
+
+ (#) LSE (low-speed external), 32 KHz oscillator used as RTC clock source.
+
+ (#) PLL , The RCC features three independent PLLs (clocked by HSI , HSE or CSI),
+ featuring three different output clocks and able to work either in integer or Fractional mode.
+ (++) A main PLL, PLL1, which is generally used to provide clocks to the CPU
+ and to some peripherals.
+ (++) Two dedicated PLLs, PLL2 and PLL3, which are used to generate the kernel clock for peripherals.
+
+
+ (#) CSS (Clock security system), once enabled 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-M NMI (Non-Mask-able Interrupt)
+ exception vector.
+
+ (#) MCO1 (micro controller clock output), used to output HSI, LSE, HSE, PLL1(PLL1_Q)
+ or HSI48 clock (through a configurable pre-scaler) on PA8 pin.
+
+ (#) MCO2 (micro controller clock output), used to output HSE, PLL2(PLL2_P), SYSCLK,
+ LSI, CSI, or PLL1(PLL1_P) clock (through a configurable pre-scaler) on PC9 pin.
+
+ [..] System, AHB and APB buses clocks configuration
+ (#) Several clock sources can be used to drive the System clock (SYSCLK): CSI,HSI,
+ HSE and PLL.
+ The AHB clock (HCLK) is derived from System core clock through configurable
+ pre-scaler and used to clock the CPU, memory and peripherals mapped
+ on AHB and APB bus of the 3 Domains (D1, D2, D3)* through configurable pre-scalers
+ and used to clock the peripherals mapped on these buses. You can use
+ "HAL_RCC_GetSysClockFreq()" function to retrieve system clock frequency.
+
+ -@- All the peripheral clocks are derived from the System clock (SYSCLK) except those
+ with dual clock domain where kernel source clock could be selected through
+ RCC_D1CCIPR,RCC_D2CCIP1R,RCC_D2CCIP2R and RCC_D3CCIPR registers.
+
+ (*) : 2 Domains (CD and SRD) for stm32h7a3xx and stm32h7b3xx family lines.
+@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, PLL1, PLL2 and PLL3 OFF
+ * - AHB, APB Bus pre-scaler 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 HAL status
+ */
+HAL_StatusTypeDef HAL_RCC_DeInit(void)
+{
+ uint32_t tickstart;
+
+ /* Increasing the CPU frequency */
+ if (FLASH_LATENCY_DEFAULT > __HAL_FLASH_GET_LATENCY())
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_DEFAULT);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if (__HAL_FLASH_GET_LATENCY() != FLASH_LATENCY_DEFAULT)
+ {
+ return HAL_ERROR;
+ }
+
+ }
+
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+
+ /* Set HSION bit */
+ SET_BIT(RCC->CR, RCC_CR_HSION);
+
+ /* Wait till HSI is ready */
+ while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set HSITRIM[6:0] bits to the reset value */
+ SET_BIT(RCC->HSICFGR, RCC_HSICFGR_HSITRIM_6);
+
+ /* Reset CFGR register */
+ CLEAR_REG(RCC->CFGR);
+
+ /* Update the SystemCoreClock and SystemD2Clock global variables */
+ SystemCoreClock = HSI_VALUE;
+ SystemD2Clock = HSI_VALUE;
+
+ /* Adapt Systick interrupt period */
+ if (HAL_InitTick(uwTickPrio) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait till clock switch is ready */
+ while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+
+ /* Reset CSION, CSIKERON, HSEON, HSI48ON, HSECSSON, HSIDIV bits */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSIKERON | RCC_CR_HSIDIV | RCC_CR_HSIDIVF | RCC_CR_CSION | RCC_CR_CSIKERON \
+ | RCC_CR_HSI48ON | RCC_CR_CSSHSEON);
+
+ /* Wait till HSE is disabled */
+ while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+
+ /* Clear PLLON bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_PLL1ON);
+
+ /* Wait till PLL is disabled */
+ while (READ_BIT(RCC->CR, RCC_CR_PLL1RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+
+ /* Reset PLL2ON bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_PLL2ON);
+
+ /* Wait till PLL2 is disabled */
+ while (READ_BIT(RCC->CR, RCC_CR_PLL2RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Get Start Tick */
+ tickstart = HAL_GetTick();
+
+ /* Reset PLL3 bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_PLL3ON);
+
+ /* Wait till PLL3 is disabled */
+ while (READ_BIT(RCC->CR, RCC_CR_PLL3RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+#if defined(RCC_D1CFGR_HPRE)
+ /* Reset D1CFGR register */
+ CLEAR_REG(RCC->D1CFGR);
+
+ /* Reset D2CFGR register */
+ CLEAR_REG(RCC->D2CFGR);
+
+ /* Reset D3CFGR register */
+ CLEAR_REG(RCC->D3CFGR);
+#else
+ /* Reset CDCFGR1 register */
+ CLEAR_REG(RCC->CDCFGR1);
+
+ /* Reset CDCFGR2 register */
+ CLEAR_REG(RCC->CDCFGR2);
+
+ /* Reset SRDCFGR register */
+ CLEAR_REG(RCC->SRDCFGR);
+#endif
+
+ /* Reset PLLCKSELR register to default value */
+ RCC->PLLCKSELR = RCC_PLLCKSELR_DIVM1_5 | RCC_PLLCKSELR_DIVM2_5 | RCC_PLLCKSELR_DIVM3_5;
+
+ /* Reset PLLCFGR register to default value */
+ WRITE_REG(RCC->PLLCFGR, 0x01FF0000U);
+
+ /* Reset PLL1DIVR register to default value */
+ WRITE_REG(RCC->PLL1DIVR, 0x01010280U);
+
+ /* Reset PLL1FRACR register */
+ CLEAR_REG(RCC->PLL1FRACR);
+
+ /* Reset PLL2DIVR register to default value */
+ WRITE_REG(RCC->PLL2DIVR, 0x01010280U);
+
+ /* Reset PLL2FRACR register */
+ CLEAR_REG(RCC->PLL2FRACR);
+
+ /* Reset PLL3DIVR register to default value */
+ WRITE_REG(RCC->PLL3DIVR, 0x01010280U);
+
+ /* Reset PLL3FRACR register */
+ CLEAR_REG(RCC->PLL3FRACR);
+
+#if defined(RCC_CR_HSEEXT)
+ /* Reset HSEEXT */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEEXT);
+#endif /* RCC_CR_HSEEXT */
+
+ /* Reset HSEBYP bit */
+ CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
+
+ /* Disable all interrupts */
+ CLEAR_REG(RCC->CIER);
+
+ /* Clear all interrupts flags */
+ WRITE_REG(RCC->CICR, 0xFFFFFFFFU);
+
+ /* Reset all RSR flags */
+ SET_BIT(RCC->RSR, RCC_RSR_RMVF);
+
+ /* Decreasing the number of wait states because of lower CPU frequency */
+ if (FLASH_LATENCY_DEFAULT < __HAL_FLASH_GET_LATENCY())
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_DEFAULT);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if (__HAL_FLASH_GET_LATENCY() != FLASH_LATENCY_DEFAULT)
+ {
+ return HAL_ERROR;
+ }
+
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @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.
+ * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
+ * supported by this function. User should request a transition to LSE Off
+ * first and then LSE On or LSE Bypass.
+ * @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
+ * supported by this function. User should request a transition to HSE Off
+ * first and then HSE On or HSE Bypass.
+ * @retval HAL status
+ */
+__weak HAL_StatusTypeDef HAL_RCC_OscConfig(const RCC_OscInitTypeDef *RCC_OscInitStruct)
+{
+ uint32_t tickstart;
+ uint32_t temp1_pllckcfg, temp2_pllckcfg;
+
+ /* Check Null pointer */
+ if (RCC_OscInitStruct == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* 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));
+
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_pllckselr = RCC->PLLCKSELR;
+ /* When the HSE is used as system clock or clock source for PLL in these cases HSE will not disabled */
+ if ((temp_sysclksrc == RCC_CFGR_SWS_HSE) || ((temp_sysclksrc == RCC_CFGR_SWS_PLL1) && ((temp_pllckselr & RCC_PLLCKSELR_PLLSRC) == RCC_PLLCKSELR_PLLSRC_HSE)))
+ {
+ if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != 0U) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
+ {
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ /* Set the new HSE configuration ---------------------------------------*/
+ __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
+
+ /* Check the HSE State */
+ if (RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == 0U)
+ {
+ if ((uint32_t)(HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSE is disabled */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != 0U)
+ {
+ if ((uint32_t)(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_HSICALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
+
+ /* When the HSI is used as system clock it will not be disabled */
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_pllckselr = RCC->PLLCKSELR;
+ if ((temp_sysclksrc == RCC_CFGR_SWS_HSI) || ((temp_sysclksrc == RCC_CFGR_SWS_PLL1) && ((temp_pllckselr & RCC_PLLCKSELR_PLLSRC) == RCC_PLLCKSELR_PLLSRC_HSI)))
+ {
+ /* When HSI is used as system clock it will not be disabled */
+ if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != 0U) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF))
+ {
+ return HAL_ERROR;
+ }
+ /* Otherwise, only HSI division and calibration are allowed */
+ else
+ {
+ /* Enable the Internal High Speed oscillator (HSI, HSIDIV2, HSIDIV4, or HSIDIV8) */
+ __HAL_RCC_HSI_CONFIG(RCC_OscInitStruct->HSIState);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == 0U)
+ {
+ if ((uint32_t)(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
+ {
+ /* Check the HSI State */
+ if ((RCC_OscInitStruct->HSIState) != RCC_HSI_OFF)
+ {
+ /* Enable the Internal High Speed oscillator (HSI, HSIDIV2,HSIDIV4, or HSIDIV8) */
+ __HAL_RCC_HSI_CONFIG(RCC_OscInitStruct->HSIState);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
+ __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
+ }
+ else
+ {
+ /* Disable the Internal High Speed oscillator (HSI). */
+ __HAL_RCC_HSI_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI is disabled */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ }
+ /*----------------------------- CSI Configuration --------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_CSI) == RCC_OSCILLATORTYPE_CSI)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_CSI(RCC_OscInitStruct->CSIState));
+ assert_param(IS_RCC_CSICALIBRATION_VALUE(RCC_OscInitStruct->CSICalibrationValue));
+
+ /* When the CSI is used as system clock it will not disabled */
+ const uint32_t temp_sysclksrc = __HAL_RCC_GET_SYSCLK_SOURCE();
+ const uint32_t temp_pllckselr = RCC->PLLCKSELR;
+ if ((temp_sysclksrc == RCC_CFGR_SWS_CSI) || ((temp_sysclksrc == RCC_CFGR_SWS_PLL1) && ((temp_pllckselr & RCC_PLLCKSELR_PLLSRC) == RCC_PLLCKSELR_PLLSRC_CSI)))
+ {
+ /* When CSI is used as system clock it will not disabled */
+ if ((__HAL_RCC_GET_FLAG(RCC_FLAG_CSIRDY) != 0U) && (RCC_OscInitStruct->CSIState != RCC_CSI_ON))
+ {
+ return HAL_ERROR;
+ }
+ /* Otherwise, just the calibration is allowed */
+ else
+ {
+ /* Adjusts the Internal High Speed oscillator (CSI) calibration value.*/
+ __HAL_RCC_CSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->CSICalibrationValue);
+ }
+ }
+ else
+ {
+ /* Check the CSI State */
+ if ((RCC_OscInitStruct->CSIState) != RCC_CSI_OFF)
+ {
+ /* Enable the Internal High Speed oscillator (CSI). */
+ __HAL_RCC_CSI_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till CSI is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_CSIRDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > CSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Adjusts the Internal High Speed oscillator (CSI) calibration value.*/
+ __HAL_RCC_CSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->CSICalibrationValue);
+ }
+ else
+ {
+ /* Disable the Internal High Speed oscillator (CSI). */
+ __HAL_RCC_CSI_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till CSI is disabled */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_CSIRDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > CSI_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) == 0U)
+ {
+ 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) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+
+ /*------------------------------ HSI48 Configuration -------------------------*/
+ if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State));
+
+ /* Check the HSI48 State */
+ if ((RCC_OscInitStruct->HSI48State) != RCC_HSI48_OFF)
+ {
+ /* Enable the Internal Low Speed oscillator (HSI48). */
+ __HAL_RCC_HSI48_ENABLE();
+
+ /* Get time-out */
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI48 is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSI48RDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Disable the Internal Low Speed oscillator (HSI48). */
+ __HAL_RCC_HSI48_DISABLE();
+
+ /* Get time-out */
+ tickstart = HAL_GetTick();
+
+ /* Wait till HSI48 is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSI48RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > HSI48_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 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) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Set the new LSE configuration -----------------------------------------*/
+ __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
+ /* Check the LSE State */
+ if ((RCC_OscInitStruct->LSEState) != RCC_LSE_OFF)
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ else
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is disabled */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != 0U)
+ {
+ 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_CFGR_SWS_PLL1)
+ {
+ if ((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
+ assert_param(IS_RCC_PLLRGE_VALUE(RCC_OscInitStruct->PLL.PLLRGE));
+ assert_param(IS_RCC_PLLVCO_VALUE(RCC_OscInitStruct->PLL.PLLVCOSEL));
+ assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
+ assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
+ assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
+ assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
+ assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));
+ assert_param(IS_RCC_PLLFRACN_VALUE(RCC_OscInitStruct->PLL.PLLFRACN));
+
+ /* 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) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure the main PLL clock source, multiplication and division factors. */
+ __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
+ RCC_OscInitStruct->PLL.PLLM,
+ RCC_OscInitStruct->PLL.PLLN,
+ RCC_OscInitStruct->PLL.PLLP,
+ RCC_OscInitStruct->PLL.PLLQ,
+ RCC_OscInitStruct->PLL.PLLR);
+
+ /* Disable PLLFRACN . */
+ __HAL_RCC_PLLFRACN_DISABLE();
+
+ /* Configure PLL PLL1FRACN */
+ __HAL_RCC_PLLFRACN_CONFIG(RCC_OscInitStruct->PLL.PLLFRACN);
+
+ /* Select PLL1 input reference frequency range: VCI */
+ __HAL_RCC_PLL_VCIRANGE(RCC_OscInitStruct->PLL.PLLRGE) ;
+
+ /* Select PLL1 output frequency range : VCO */
+ __HAL_RCC_PLL_VCORANGE(RCC_OscInitStruct->PLL.PLLVCOSEL) ;
+
+ /* Enable PLL System Clock output. */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVP);
+
+ /* Enable PLL1Q Clock output. */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* Enable PLL1R Clock output. */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVR);
+
+ /* Enable PLL1FRACN . */
+ __HAL_RCC_PLLFRACN_ENABLE();
+
+ /* 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) == 0U)
+ {
+ 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 disabled */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Do not return HAL_ERROR if request repeats the current configuration */
+ temp1_pllckcfg = RCC->PLLCKSELR;
+ temp2_pllckcfg = RCC->PLL1DIVR;
+ if (((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF) ||
+ (READ_BIT(temp1_pllckcfg, RCC_PLLCKSELR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
+ ((READ_BIT(temp1_pllckcfg, RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos) != RCC_OscInitStruct->PLL.PLLM) ||
+ (READ_BIT(temp2_pllckcfg, RCC_PLL1DIVR_N1) != (RCC_OscInitStruct->PLL.PLLN - 1U)) ||
+ ((READ_BIT(temp2_pllckcfg, RCC_PLL1DIVR_P1) >> RCC_PLL1DIVR_P1_Pos) != (RCC_OscInitStruct->PLL.PLLP - 1U)) ||
+ ((READ_BIT(temp2_pllckcfg, RCC_PLL1DIVR_Q1) >> RCC_PLL1DIVR_Q1_Pos) != (RCC_OscInitStruct->PLL.PLLQ - 1U)) ||
+ ((READ_BIT(temp2_pllckcfg, RCC_PLL1DIVR_R1) >> RCC_PLL1DIVR_R1_Pos) != (RCC_OscInitStruct->PLL.PLLR - 1U)))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ /* Check if only fractional part needs to be updated */
+ temp1_pllckcfg = ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1) >> RCC_PLL1FRACR_FRACN1_Pos);
+ if (RCC_OscInitStruct->PLL.PLLFRACN != temp1_pllckcfg)
+ {
+ assert_param(IS_RCC_PLLFRACN_VALUE(RCC_OscInitStruct->PLL.PLLFRACN));
+ /* Disable PLL1FRACEN */
+ __HAL_RCC_PLLFRACN_DISABLE();
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+ /* Wait at least 2 CK_REF (PLL input source divided by M) period to make sure next latched value will be taken into account. */
+ while ((HAL_GetTick() - tickstart) < PLL_FRAC_TIMEOUT_VALUE)
+ {
+ }
+ /* Configure PLL1 PLL1FRACN */
+ __HAL_RCC_PLLFRACN_CONFIG(RCC_OscInitStruct->PLL.PLLFRACN);
+ /* Enable PLL1FRACEN to latch new value. */
+ __HAL_RCC_PLLFRACN_ENABLE();
+ }
+ }
+ }
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the CPU, AHB and APB buses 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 Core Clock Frequency
+ * and updated by HAL_InitTick() function called within this function
+ *
+ * @note The HSI is used (enabled by hardware) as system clock source after
+ * start-up 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 start-up 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
+ * D1CPRE[3:0] bits to ensure that Domain1 core clock not exceed the maximum allowed frequency
+ * (for more details refer to section above "Initialization/de-initialization functions")
+ * @retval None
+ */
+HAL_StatusTypeDef HAL_RCC_ClockConfig(const RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
+{
+ HAL_StatusTypeDef halstatus;
+ uint32_t tickstart;
+ uint32_t common_system_clock;
+
+ /* Check Null pointer */
+ if (RCC_ClkInitStruct == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
+ assert_param(IS_FLASH_LATENCY(FLatency));
+
+ /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
+ must be correctly programmed according to the frequency of the CPU clock
+ (HCLK) and the supply voltage of the device. */
+
+ /* Increasing the CPU frequency */
+ if (FLatency > __HAL_FLASH_GET_LATENCY())
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLatency);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if (__HAL_FLASH_GET_LATENCY() != FLatency)
+ {
+ return HAL_ERROR;
+ }
+
+ }
+
+ /* Increasing the BUS frequency divider */
+ /*-------------------------- D1PCLK1/CDPCLK1 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_D1PCLK1) == RCC_CLOCKTYPE_D1PCLK1)
+ {
+#if defined (RCC_D1CFGR_D1PPRE)
+ if ((RCC_ClkInitStruct->APB3CLKDivider) > (RCC->D1CFGR & RCC_D1CFGR_D1PPRE))
+ {
+ assert_param(IS_RCC_D1PCLK1(RCC_ClkInitStruct->APB3CLKDivider));
+ MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1PPRE, RCC_ClkInitStruct->APB3CLKDivider);
+ }
+#else
+ if ((RCC_ClkInitStruct->APB3CLKDivider) > (RCC->CDCFGR1 & RCC_CDCFGR1_CDPPRE))
+ {
+ assert_param(IS_RCC_CDPCLK1(RCC_ClkInitStruct->APB3CLKDivider));
+ MODIFY_REG(RCC->CDCFGR1, RCC_CDCFGR1_CDPPRE, RCC_ClkInitStruct->APB3CLKDivider);
+ }
+#endif
+ }
+
+ /*-------------------------- PCLK1 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
+ {
+#if defined (RCC_D2CFGR_D2PPRE1)
+ if ((RCC_ClkInitStruct->APB1CLKDivider) > (RCC->D2CFGR & RCC_D2CFGR_D2PPRE1))
+ {
+ assert_param(IS_RCC_PCLK1(RCC_ClkInitStruct->APB1CLKDivider));
+ MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE1, (RCC_ClkInitStruct->APB1CLKDivider));
+ }
+#else
+ if ((RCC_ClkInitStruct->APB1CLKDivider) > (RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE1))
+ {
+ assert_param(IS_RCC_PCLK1(RCC_ClkInitStruct->APB1CLKDivider));
+ MODIFY_REG(RCC->CDCFGR2, RCC_CDCFGR2_CDPPRE1, (RCC_ClkInitStruct->APB1CLKDivider));
+ }
+#endif
+ }
+ /*-------------------------- PCLK2 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
+ {
+#if defined(RCC_D2CFGR_D2PPRE2)
+ if ((RCC_ClkInitStruct->APB2CLKDivider) > (RCC->D2CFGR & RCC_D2CFGR_D2PPRE2))
+ {
+ assert_param(IS_RCC_PCLK2(RCC_ClkInitStruct->APB2CLKDivider));
+ MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE2, (RCC_ClkInitStruct->APB2CLKDivider));
+ }
+#else
+ if ((RCC_ClkInitStruct->APB2CLKDivider) > (RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE2))
+ {
+ assert_param(IS_RCC_PCLK2(RCC_ClkInitStruct->APB2CLKDivider));
+ MODIFY_REG(RCC->CDCFGR2, RCC_CDCFGR2_CDPPRE2, (RCC_ClkInitStruct->APB2CLKDivider));
+ }
+#endif
+ }
+
+ /*-------------------------- D3PCLK1 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_D3PCLK1) == RCC_CLOCKTYPE_D3PCLK1)
+ {
+#if defined(RCC_D3CFGR_D3PPRE)
+ if ((RCC_ClkInitStruct->APB4CLKDivider) > (RCC->D3CFGR & RCC_D3CFGR_D3PPRE))
+ {
+ assert_param(IS_RCC_D3PCLK1(RCC_ClkInitStruct->APB4CLKDivider));
+ MODIFY_REG(RCC->D3CFGR, RCC_D3CFGR_D3PPRE, (RCC_ClkInitStruct->APB4CLKDivider));
+ }
+#else
+ if ((RCC_ClkInitStruct->APB4CLKDivider) > (RCC->SRDCFGR & RCC_SRDCFGR_SRDPPRE))
+ {
+ assert_param(IS_RCC_D3PCLK1(RCC_ClkInitStruct->APB4CLKDivider));
+ MODIFY_REG(RCC->SRDCFGR, RCC_SRDCFGR_SRDPPRE, (RCC_ClkInitStruct->APB4CLKDivider));
+ }
+#endif
+ }
+
+ /*-------------------------- HCLK Configuration --------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
+ {
+#if defined (RCC_D1CFGR_HPRE)
+ if ((RCC_ClkInitStruct->AHBCLKDivider) > (RCC->D1CFGR & RCC_D1CFGR_HPRE))
+ {
+ /* Set the new HCLK clock divider */
+ assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
+ MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
+ }
+#else
+ if ((RCC_ClkInitStruct->AHBCLKDivider) > (RCC->CDCFGR1 & RCC_CDCFGR1_HPRE))
+ {
+ /* Set the new HCLK clock divider */
+ assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
+ MODIFY_REG(RCC->CDCFGR1, RCC_CDCFGR1_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
+ }
+#endif
+ }
+
+ /*------------------------- SYSCLK Configuration -------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
+ {
+ assert_param(IS_RCC_SYSCLK(RCC_ClkInitStruct->SYSCLKDivider));
+ assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
+#if defined(RCC_D1CFGR_D1CPRE)
+ MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1CPRE, RCC_ClkInitStruct->SYSCLKDivider);
+#else
+ MODIFY_REG(RCC->CDCFGR1, RCC_CDCFGR1_CDCPRE, RCC_ClkInitStruct->SYSCLKDivider);
+#endif
+ /* 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) == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* PLL is selected as System Clock Source */
+ else if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
+ {
+ /* Check the PLL ready flag */
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* CSI is selected as System Clock Source */
+ else if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_CSI)
+ {
+ /* Check the PLL ready flag */
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_CSIRDY) == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ /* HSI is selected as System Clock Source */
+ else
+ {
+ /* Check the HSI ready flag */
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == 0U)
+ {
+ return HAL_ERROR;
+ }
+ }
+ MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
+ {
+ if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ }
+
+ /* Decreasing the BUS frequency divider */
+ /*-------------------------- HCLK Configuration --------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
+ {
+#if defined(RCC_D1CFGR_HPRE)
+ if ((RCC_ClkInitStruct->AHBCLKDivider) < (RCC->D1CFGR & RCC_D1CFGR_HPRE))
+ {
+ /* Set the new HCLK clock divider */
+ assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
+ MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
+ }
+#else
+ if ((RCC_ClkInitStruct->AHBCLKDivider) < (RCC->CDCFGR1 & RCC_CDCFGR1_HPRE))
+ {
+ /* Set the new HCLK clock divider */
+ assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
+ MODIFY_REG(RCC->CDCFGR1, RCC_CDCFGR1_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
+ }
+#endif
+ }
+
+ /* Decreasing the number of wait states because of lower CPU frequency */
+ if (FLatency < __HAL_FLASH_GET_LATENCY())
+ {
+ /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
+ __HAL_FLASH_SET_LATENCY(FLatency);
+
+ /* Check that the new number of wait states is taken into account to access the Flash
+ memory by reading the FLASH_ACR register */
+ if (__HAL_FLASH_GET_LATENCY() != FLatency)
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ /*-------------------------- D1PCLK1/CDPCLK Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_D1PCLK1) == RCC_CLOCKTYPE_D1PCLK1)
+ {
+#if defined(RCC_D1CFGR_D1PPRE)
+ if ((RCC_ClkInitStruct->APB3CLKDivider) < (RCC->D1CFGR & RCC_D1CFGR_D1PPRE))
+ {
+ assert_param(IS_RCC_D1PCLK1(RCC_ClkInitStruct->APB3CLKDivider));
+ MODIFY_REG(RCC->D1CFGR, RCC_D1CFGR_D1PPRE, RCC_ClkInitStruct->APB3CLKDivider);
+ }
+#else
+ if ((RCC_ClkInitStruct->APB3CLKDivider) < (RCC->CDCFGR1 & RCC_CDCFGR1_CDPPRE))
+ {
+ assert_param(IS_RCC_CDPCLK1(RCC_ClkInitStruct->APB3CLKDivider));
+ MODIFY_REG(RCC->CDCFGR1, RCC_CDCFGR1_CDPPRE, RCC_ClkInitStruct->APB3CLKDivider);
+ }
+#endif
+ }
+
+ /*-------------------------- PCLK1 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
+ {
+#if defined(RCC_D2CFGR_D2PPRE1)
+ if ((RCC_ClkInitStruct->APB1CLKDivider) < (RCC->D2CFGR & RCC_D2CFGR_D2PPRE1))
+ {
+ assert_param(IS_RCC_PCLK1(RCC_ClkInitStruct->APB1CLKDivider));
+ MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE1, (RCC_ClkInitStruct->APB1CLKDivider));
+ }
+#else
+ if ((RCC_ClkInitStruct->APB1CLKDivider) < (RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE1))
+ {
+ assert_param(IS_RCC_PCLK1(RCC_ClkInitStruct->APB1CLKDivider));
+ MODIFY_REG(RCC->CDCFGR2, RCC_CDCFGR2_CDPPRE1, (RCC_ClkInitStruct->APB1CLKDivider));
+ }
+#endif
+ }
+
+ /*-------------------------- PCLK2 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
+ {
+#if defined (RCC_D2CFGR_D2PPRE2)
+ if ((RCC_ClkInitStruct->APB2CLKDivider) < (RCC->D2CFGR & RCC_D2CFGR_D2PPRE2))
+ {
+ assert_param(IS_RCC_PCLK2(RCC_ClkInitStruct->APB2CLKDivider));
+ MODIFY_REG(RCC->D2CFGR, RCC_D2CFGR_D2PPRE2, (RCC_ClkInitStruct->APB2CLKDivider));
+ }
+#else
+ if ((RCC_ClkInitStruct->APB2CLKDivider) < (RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE2))
+ {
+ assert_param(IS_RCC_PCLK2(RCC_ClkInitStruct->APB2CLKDivider));
+ MODIFY_REG(RCC->CDCFGR2, RCC_CDCFGR2_CDPPRE2, (RCC_ClkInitStruct->APB2CLKDivider));
+ }
+#endif
+ }
+
+ /*-------------------------- D3PCLK1/SRDPCLK1 Configuration ---------------------------*/
+ if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_D3PCLK1) == RCC_CLOCKTYPE_D3PCLK1)
+ {
+#if defined(RCC_D3CFGR_D3PPRE)
+ if ((RCC_ClkInitStruct->APB4CLKDivider) < (RCC->D3CFGR & RCC_D3CFGR_D3PPRE))
+ {
+ assert_param(IS_RCC_D3PCLK1(RCC_ClkInitStruct->APB4CLKDivider));
+ MODIFY_REG(RCC->D3CFGR, RCC_D3CFGR_D3PPRE, (RCC_ClkInitStruct->APB4CLKDivider));
+ }
+#else
+ if ((RCC_ClkInitStruct->APB4CLKDivider) < (RCC->SRDCFGR & RCC_SRDCFGR_SRDPPRE))
+ {
+ assert_param(IS_RCC_SRDPCLK1(RCC_ClkInitStruct->APB4CLKDivider));
+ MODIFY_REG(RCC->SRDCFGR, RCC_SRDCFGR_SRDPPRE, (RCC_ClkInitStruct->APB4CLKDivider));
+ }
+#endif
+ }
+
+ /* Update the SystemCoreClock global variable */
+#if defined(RCC_D1CFGR_D1CPRE)
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE) >> RCC_D1CFGR_D1CPRE_Pos]) & 0x1FU);
+#else
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE) >> RCC_CDCFGR1_CDCPRE_Pos]) & 0x1FU);
+#endif
+
+#if defined(RCC_D1CFGR_HPRE)
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE) >> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
+#else
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE) >> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
+#endif
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ SystemCoreClock = SystemD2Clock;
+#else
+ SystemCoreClock = common_system_clock;
+#endif /* DUAL_CORE && CORE_CM4 */
+
+ /* Configure the source of time base considering new system clocks settings*/
+ halstatus = HAL_InitTick(uwTickPrio);
+
+ return halstatus;
+}
+
+/**
+ * @}
+ */
+
+/** @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_PLL1QCLK: PLL1Q clock selected as MCO1 source
+ * @arg RCC_MCO1SOURCE_HSI48: HSI48 (48MHZ) selected as MCO1 source
+ * @arg RCC_MCO2SOURCE_SYSCLK: System clock (SYSCLK) selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_PLL2PCLK: PLL2P clock selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_HSE: HSE clock selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_PLLCLK: PLL1P clock selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_CSICLK: CSI clock selected as MCO2 source
+ * @arg RCC_MCO2SOURCE_LSICLK: LSI clock selected as MCO2 source
+ * @param RCC_MCODiv: specifies the MCOx pre-scaler.
+ * This parameter can be one of the following values:
+ * @arg RCC_MCODIV_1 up to RCC_MCODIV_15 : divider 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_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
+ HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
+
+ /* Mask MCO1 and MCO1PRE[3:0] bits then Select MCO1 clock source and pre-scaler */
+ 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_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
+ HAL_GPIO_Init(MCO2_GPIO_PORT, &GPIO_InitStruct);
+
+ /* Mask MCO2 and MCO2PRE[3:0] bits then Select MCO2 clock source and pre-scaler */
+ MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCO2 | RCC_CFGR_MCO2PRE), (RCC_MCOSource | (RCC_MCODiv << 7U)));
+ }
+}
+
+/**
+ * @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-M NMI (Non-Mask-able Interrupt) exception vector.
+ * @retval None
+ */
+void HAL_RCC_EnableCSS(void)
+{
+ SET_BIT(RCC->CR, RCC_CR_CSSHSEON) ;
+}
+
+/**
+ * @brief Disables the Clock Security System.
+ * @retval None
+ */
+void HAL_RCC_DisableCSS(void)
+{
+ CLEAR_BIT(RCC->CR, RCC_CR_CSSHSEON);
+}
+
+/**
+ * @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 CSI, function returns values based on CSI_VALUE(*)
+ * @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 CSI_VALUE(*),
+ * HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
+ * @note (*) CSI_VALUE is a constant defined in stm32h7xx_hal_conf.h file (default value
+ * 4 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note (**) HSI_VALUE is a constant defined in stm32h7xx_hal_conf.h file (default value
+ * 64 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ * @note (***) HSE_VALUE is a constant defined in stm32h7xx_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
+ * baud rate 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 pllp, pllsource, pllm, pllfracen, hsivalue;
+ float_t fracn1, pllvco;
+ uint32_t sysclockfreq;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+
+ switch (RCC->CFGR & RCC_CFGR_SWS)
+ {
+ case RCC_CFGR_SWS_HSI: /* HSI used as system clock source */
+
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ sysclockfreq = (uint32_t)(HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+ else
+ {
+ sysclockfreq = (uint32_t) HSI_VALUE;
+ }
+
+ break;
+
+ case RCC_CFGR_SWS_CSI: /* CSI used as system clock source */
+ sysclockfreq = CSI_VALUE;
+ break;
+
+ case RCC_CFGR_SWS_HSE: /* HSE used as system clock source */
+ sysclockfreq = HSE_VALUE;
+ break;
+
+ case RCC_CFGR_SWS_PLL1: /* PLL1 used as system clock source */
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN
+ SYSCLK = PLL_VCO / PLLR
+ */
+ pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
+ pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> 4) ;
+ pllfracen = ((RCC-> PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) >> RCC_PLLCFGR_PLL1FRACEN_Pos);
+ fracn1 = (float_t)(uint32_t)(pllfracen * ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1) >> 3));
+
+ if (pllm != 0U)
+ {
+ switch (pllsource)
+ {
+ case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ hsivalue = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ pllvco = ((float_t)hsivalue / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ }
+ else
+ {
+ pllvco = ((float_t)HSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ }
+ break;
+
+ case RCC_PLLSOURCE_CSI: /* CSI used as PLL clock source */
+ pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ default:
+ pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ break;
+ }
+ pllp = (((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >> 9) + 1U) ;
+ sysclockfreq = (uint32_t)(float_t)(pllvco / (float_t)pllp);
+ }
+ else
+ {
+ sysclockfreq = 0U;
+ }
+ break;
+
+ default:
+ sysclockfreq = CSI_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 SystemD2Clock CMSIS variable is used to store System domain2 Clock Frequency
+ * and updated within this function
+ * @retval HCLK frequency
+ */
+uint32_t HAL_RCC_GetHCLKFreq(void)
+{
+ uint32_t common_system_clock;
+
+#if defined(RCC_D1CFGR_D1CPRE)
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> (D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE) >> RCC_D1CFGR_D1CPRE_Pos] & 0x1FU);
+#else
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> (D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE) >> RCC_CDCFGR1_CDCPRE_Pos] & 0x1FU);
+#endif
+
+#if defined(RCC_D1CFGR_HPRE)
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE) >> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
+#else
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE) >> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
+#endif
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ SystemCoreClock = SystemD2Clock;
+#else
+ SystemCoreClock = common_system_clock;
+#endif /* DUAL_CORE && CORE_CM4 */
+
+ return SystemD2Clock;
+}
+
+
+/**
+ * @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)
+{
+#if defined (RCC_D2CFGR_D2PPRE1)
+ /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> ((D1CorePrescTable[(RCC->D2CFGR & RCC_D2CFGR_D2PPRE1) >> RCC_D2CFGR_D2PPRE1_Pos]) & 0x1FU));
+#else
+ /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> ((D1CorePrescTable[(RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE1) >> RCC_CDCFGR2_CDPPRE1_Pos]) & 0x1FU));
+#endif
+}
+
+
+/**
+ * @brief Returns the D2 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 PCLK1 frequency
+ */
+uint32_t HAL_RCC_GetPCLK2Freq(void)
+{
+ /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
+#if defined(RCC_D2CFGR_D2PPRE2)
+ return (HAL_RCC_GetHCLKFreq() >> ((D1CorePrescTable[(RCC->D2CFGR & RCC_D2CFGR_D2PPRE2) >> RCC_D2CFGR_D2PPRE2_Pos]) & 0x1FU));
+#else
+ return (HAL_RCC_GetHCLKFreq() >> ((D1CorePrescTable[(RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE2) >> RCC_CDCFGR2_CDPPRE2_Pos]) & 0x1FU));
+#endif
+}
+
+/**
+ * @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_CSI | \
+ RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48;
+
+ /* Get the HSE configuration -----------------------------------------------*/
+#if defined(RCC_CR_HSEEXT)
+ if ((RCC->CR & (RCC_CR_HSEBYP | RCC_CR_HSEEXT)) == RCC_CR_HSEBYP)
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
+ }
+ else if ((RCC->CR & (RCC_CR_HSEBYP | RCC_CR_HSEEXT)) == (RCC_CR_HSEBYP | RCC_CR_HSEEXT))
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS_DIGITAL;
+ }
+ else if ((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON)
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
+ }
+#else
+ 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;
+ }
+#endif /* RCC_CR_HSEEXT */
+
+ /* Get the CSI configuration -----------------------------------------------*/
+ if ((RCC->CR & RCC_CR_CSION) == RCC_CR_CSION)
+ {
+ RCC_OscInitStruct->CSIState = RCC_CSI_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->CSIState = RCC_CSI_OFF;
+ }
+
+#if defined(RCC_VER_X)
+ if (HAL_GetREVID() <= REV_ID_Y)
+ {
+ RCC_OscInitStruct->CSICalibrationValue = (uint32_t)(READ_BIT(RCC->HSICFGR, HAL_RCC_REV_Y_CSITRIM_Msk) >> HAL_RCC_REV_Y_CSITRIM_Pos);
+ }
+ else
+ {
+ RCC_OscInitStruct->CSICalibrationValue = (uint32_t)(READ_BIT(RCC->CSICFGR, RCC_CSICFGR_CSITRIM) >> RCC_CSICFGR_CSITRIM_Pos);
+ }
+#else
+ RCC_OscInitStruct->CSICalibrationValue = (uint32_t)(READ_BIT(RCC->CSICFGR, RCC_CSICFGR_CSITRIM) >> RCC_CSICFGR_CSITRIM_Pos);
+#endif /*RCC_VER_X*/
+
+ /* 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;
+ }
+
+#if defined(RCC_VER_X)
+ if (HAL_GetREVID() <= REV_ID_Y)
+ {
+ RCC_OscInitStruct->HSICalibrationValue = (uint32_t)(READ_BIT(RCC->HSICFGR, HAL_RCC_REV_Y_HSITRIM_Msk) >> HAL_RCC_REV_Y_HSITRIM_Pos);
+ }
+ else
+ {
+ RCC_OscInitStruct->HSICalibrationValue = (uint32_t)(READ_BIT(RCC->HSICFGR, RCC_HSICFGR_HSITRIM) >> RCC_HSICFGR_HSITRIM_Pos);
+ }
+#else
+ RCC_OscInitStruct->HSICalibrationValue = (uint32_t)(READ_BIT(RCC->HSICFGR, RCC_HSICFGR_HSITRIM) >> RCC_HSICFGR_HSITRIM_Pos);
+#endif /*RCC_VER_X*/
+
+ /* Get the LSE configuration -----------------------------------------------*/
+#if defined(RCC_BDCR_LSEEXT)
+ if ((RCC->BDCR & (RCC_BDCR_LSEBYP | RCC_BDCR_LSEEXT)) == RCC_BDCR_LSEBYP)
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
+ }
+ else if ((RCC->BDCR & (RCC_BDCR_LSEBYP | RCC_BDCR_LSEEXT)) == (RCC_BDCR_LSEBYP | RCC_BDCR_LSEEXT))
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS_DIGITAL;
+ }
+ else if ((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
+ }
+#else
+ 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;
+ }
+#endif /* RCC_BDCR_LSEEXT */
+
+ /* 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 HSI48 configuration ---------------------------------------------*/
+ if ((RCC->CR & RCC_CR_HSI48ON) == RCC_CR_HSI48ON)
+ {
+ RCC_OscInitStruct->HSI48State = RCC_HSI48_ON;
+ }
+ else
+ {
+ RCC_OscInitStruct->HSI48State = RCC_HSI48_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->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
+ RCC_OscInitStruct->PLL.PLLM = (uint32_t)((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos);
+ RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_N1) >> RCC_PLL1DIVR_N1_Pos) + 1U;
+ RCC_OscInitStruct->PLL.PLLR = (uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_R1) >> RCC_PLL1DIVR_R1_Pos) + 1U;
+ RCC_OscInitStruct->PLL.PLLP = (uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >> RCC_PLL1DIVR_P1_Pos) + 1U;
+ RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_Q1) >> RCC_PLL1DIVR_Q1_Pos) + 1U;
+ RCC_OscInitStruct->PLL.PLLRGE = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLL1RGE));
+ RCC_OscInitStruct->PLL.PLLVCOSEL = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLL1VCOSEL) >> RCC_PLLCFGR_PLL1VCOSEL_Pos);
+ RCC_OscInitStruct->PLL.PLLFRACN = (uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1) >> RCC_PLL1FRACR_FRACN1_Pos));
+}
+
+/**
+ * @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_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 |
+ RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D3PCLK1 ;
+
+ /* Get the SYSCLK configuration --------------------------------------------*/
+ RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW);
+
+#if defined(RCC_D1CFGR_D1CPRE)
+ /* Get the SYSCLK configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->SYSCLKDivider = (uint32_t)(RCC->D1CFGR & RCC_D1CFGR_D1CPRE);
+
+ /* Get the D1HCLK configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->D1CFGR & RCC_D1CFGR_HPRE);
+
+ /* Get the APB3 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB3CLKDivider = (uint32_t)(RCC->D1CFGR & RCC_D1CFGR_D1PPRE);
+
+ /* Get the APB1 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->D2CFGR & RCC_D2CFGR_D2PPRE1);
+
+ /* Get the APB2 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)(RCC->D2CFGR & RCC_D2CFGR_D2PPRE2);
+
+ /* Get the APB4 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB4CLKDivider = (uint32_t)(RCC->D3CFGR & RCC_D3CFGR_D3PPRE);
+#else
+ /* Get the SYSCLK configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->SYSCLKDivider = (uint32_t)(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE);
+
+ /* Get the D1HCLK configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE);
+
+ /* Get the APB3 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB3CLKDivider = (uint32_t)(RCC->CDCFGR1 & RCC_CDCFGR1_CDPPRE);
+
+ /* Get the APB1 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE1);
+
+ /* Get the APB2 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)(RCC->CDCFGR2 & RCC_CDCFGR2_CDPPRE2);
+
+ /* Get the APB4 configuration ----------------------------------------------*/
+ RCC_ClkInitStruct->APB4CLKDivider = (uint32_t)(RCC->SRDCFGR & RCC_SRDCFGR_SRDPPRE);
+#endif
+
+ /* 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 */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
new file mode 100755
index 0000000..25307c3
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_rcc_ex.c
@@ -0,0 +1,3935 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_rcc_ex.c
+ * @author MCD Application Team
+ * @brief Extended RCC HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities RCC extension peripheral:
+ * + Extended Peripheral Control functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file in
+ * the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup RCCEx RCCEx
+ * @brief RCC HAL module driver
+ * @{
+ */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/** @defgroup RCCEx_Private_defines RCCEx Private Defines
+ * @{
+ */
+#define PLL2_TIMEOUT_VALUE PLL_TIMEOUT_VALUE /* 2 ms */
+#define PLL3_TIMEOUT_VALUE PLL_TIMEOUT_VALUE /* 2 ms */
+
+#define DIVIDER_P_UPDATE 0U
+#define DIVIDER_Q_UPDATE 1U
+#define DIVIDER_R_UPDATE 2U
+/**
+ * @}
+ */
+
+/* Private macros ------------------------------------------------------------*/
+/** @defgroup RCCEx_Private_Macros RCCEx Private Macros
+ * @{
+ */
+/**
+ * @}
+ */
+
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static HAL_StatusTypeDef RCCEx_PLL2_Config(const RCC_PLL2InitTypeDef *pll2, uint32_t Divider);
+static HAL_StatusTypeDef RCCEx_PLL3_Config(const RCC_PLL3InitTypeDef *pll3, uint32_t Divider);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
+ * @{
+ */
+
+/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
+ * @brief Extended Peripheral Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Peripheral Control functions #####
+ ===============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control the RCC Clocks
+ frequencies.
+ [..]
+ (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
+ select the RTC clock source; in this case the Backup domain will be reset in
+ order to modify the RTC Clock source, as consequence RTC registers (including
+ the backup registers) and RCC_BDCR register are set to their reset values.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief 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 (SDMMC, CKPER, FMC, QSPI*, OSPI*, DSI, SPI45, SPDIF, DFSDM1, DFSDM2*, FDCAN, SWPMI, SAI23*,SAI2A*, SAI2B*, SAI1, SPI123,
+ * USART234578, USART16 (USART16910*), RNG, HRTIM1*, I2C123 (I2C1235*), USB, CEC, LPTIM1, LPUART1, I2C4, LPTIM2, LPTIM345, ADC,
+ * SAI4A*, SAI4B*, SPI6, RTC).
+ * @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) are set to their reset values.
+ *
+ * (*) : Available on some STM32H7 lines only.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ uint32_t tmpreg;
+ uint32_t tickstart;
+ HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */
+ HAL_StatusTypeDef status = HAL_OK; /* Final status */
+
+ /*---------------------------- SPDIFRX configuration -------------------------------*/
+
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPDIFRX) == RCC_PERIPHCLK_SPDIFRX)
+ {
+
+ switch (PeriphClkInit->SpdifrxClockSelection)
+ {
+ case RCC_SPDIFRXCLKSOURCE_PLL: /* PLL is used as clock source for SPDIFRX*/
+ /* Enable PLL1Q Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SPDIFRX clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPDIFRXCLKSOURCE_PLL2: /* PLL2 is used as clock source for SPDIFRX*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_R_UPDATE);
+
+ /* SPDIFRX clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPDIFRXCLKSOURCE_PLL3: /* PLL3 is used as clock source for SPDIFRX*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE);
+
+ /* SPDIFRX clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPDIFRXCLKSOURCE_HSI:
+ /* Internal OSC clock is used as source of SPDIFRX clock*/
+ /* SPDIFRX clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SPDIFRX clock*/
+ __HAL_RCC_SPDIFRX_CONFIG(PeriphClkInit->SpdifrxClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- SAI1 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)
+ {
+ switch (PeriphClkInit->Sai1ClockSelection)
+ {
+ case RCC_SAI1CLKSOURCE_PLL: /* PLL is used as clock source for SAI1*/
+ /* Enable SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_PLL2: /* PLL2 is used as clock source for SAI1*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_PLL3: /* PLL3 is used as clock source for SAI1*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_PIN:
+ /* External clock is used as source of SAI1 clock*/
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI1CLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SAI1 clock */
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI1 clock*/
+ __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+#if defined(SAI3)
+ /*---------------------------- SAI2/3 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI23) == RCC_PERIPHCLK_SAI23)
+ {
+ switch (PeriphClkInit->Sai23ClockSelection)
+ {
+ case RCC_SAI23CLKSOURCE_PLL: /* PLL is used as clock source for SAI2/3 */
+ /* Enable SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SAI2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI23CLKSOURCE_PLL2: /* PLL2 is used as clock source for SAI2/3 */
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SAI2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI23CLKSOURCE_PLL3: /* PLL3 is used as clock source for SAI2/3 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SAI2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI23CLKSOURCE_PIN:
+ /* External clock is used as source of SAI2/3 clock*/
+ /* SAI2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI23CLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SAI2/3 clock */
+ /* SAI2/3 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI2/3 clock*/
+ __HAL_RCC_SAI23_CONFIG(PeriphClkInit->Sai23ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+#endif /* SAI3 */
+
+#if defined(RCC_CDCCIP1R_SAI2ASEL)
+ /*---------------------------- SAI2A configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2A) == RCC_PERIPHCLK_SAI2A)
+ {
+ switch (PeriphClkInit->Sai2AClockSelection)
+ {
+ case RCC_SAI2ACLKSOURCE_PLL: /* PLL is used as clock source for SAI2A */
+ /* Enable SAI2A Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SAI2A clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2ACLKSOURCE_PLL2: /* PLL2 is used as clock source for SAI2A */
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SAI2A clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2ACLKSOURCE_PLL3: /* PLL3 is used as clock source for SAI2A */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SAI2A clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2ACLKSOURCE_PIN:
+ /* External clock is used as source of SAI2A clock*/
+ /* SAI2A clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2ACLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SAI2A clock */
+ /* SAI2A clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2ACLKSOURCE_SPDIF:
+ /* SPDIF clock is used as source of SAI2A clock */
+ /* SAI2A clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI2A clock*/
+ __HAL_RCC_SAI2A_CONFIG(PeriphClkInit->Sai2AClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*SAI2A*/
+
+#if defined(RCC_CDCCIP1R_SAI2BSEL)
+
+ /*---------------------------- SAI2B configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2B) == RCC_PERIPHCLK_SAI2B)
+ {
+ switch (PeriphClkInit->Sai2BClockSelection)
+ {
+ case RCC_SAI2BCLKSOURCE_PLL: /* PLL is used as clock source for SAI2B */
+ /* Enable SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SAI2B clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2BCLKSOURCE_PLL2: /* PLL2 is used as clock source for SAI2B */
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SAI2B clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2BCLKSOURCE_PLL3: /* PLL3 is used as clock source for SAI2B */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SAI2B clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2BCLKSOURCE_PIN:
+ /* External clock is used as source of SAI2B clock*/
+ /* SAI2B clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2BCLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SAI2B clock */
+ /* SAI2B clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI2BCLKSOURCE_SPDIF:
+ /* SPDIF clock is used as source of SAI2B clock */
+ /* SAI2B clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI2B clock*/
+ __HAL_RCC_SAI2B_CONFIG(PeriphClkInit->Sai2BClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*SAI2B*/
+
+#if defined(SAI4)
+ /*---------------------------- SAI4A configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI4A) == RCC_PERIPHCLK_SAI4A)
+ {
+ switch (PeriphClkInit->Sai4AClockSelection)
+ {
+ case RCC_SAI4ACLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/
+ /* Enable SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4ACLKSOURCE_PLL2: /* PLL2 is used as clock source for SAI2*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SAI2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4ACLKSOURCE_PLL3: /* PLL3 is used as clock source for SAI2*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4ACLKSOURCE_PIN:
+ /* External clock is used as source of SAI2 clock*/
+ /* SAI2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4ACLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SAI2 clock */
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+#if defined(RCC_VER_3_0)
+ case RCC_SAI4ACLKSOURCE_SPDIF:
+ /* SPDIF clock is used as source of SAI4A clock */
+ /* SAI4A clock source configuration done later after clock selection check */
+ break;
+#endif /* RCC_VER_3_0 */
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI4A clock*/
+ __HAL_RCC_SAI4A_CONFIG(PeriphClkInit->Sai4AClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+ /*---------------------------- SAI4B configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI4B) == RCC_PERIPHCLK_SAI4B)
+ {
+ switch (PeriphClkInit->Sai4BClockSelection)
+ {
+ case RCC_SAI4BCLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/
+ /* Enable SAI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4BCLKSOURCE_PLL2: /* PLL2 is used as clock source for SAI2*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SAI2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4BCLKSOURCE_PLL3: /* PLL3 is used as clock source for SAI2*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4BCLKSOURCE_PIN:
+ /* External clock is used as source of SAI2 clock*/
+ /* SAI2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SAI4BCLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SAI2 clock */
+ /* SAI1 clock source configuration done later after clock selection check */
+ break;
+
+#if defined(RCC_VER_3_0)
+ case RCC_SAI4BCLKSOURCE_SPDIF:
+ /* SPDIF clock is used as source of SAI4B clock */
+ /* SAI4B clock source configuration done later after clock selection check */
+ break;
+#endif /* RCC_VER_3_0 */
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SAI4B clock*/
+ __HAL_RCC_SAI4B_CONFIG(PeriphClkInit->Sai4BClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*SAI4*/
+
+#if defined(QUADSPI)
+ /*---------------------------- QSPI configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_QSPI) == RCC_PERIPHCLK_QSPI)
+ {
+ switch (PeriphClkInit->QspiClockSelection)
+ {
+ case RCC_QSPICLKSOURCE_PLL: /* PLL is used as clock source for QSPI*/
+ /* Enable QSPI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* QSPI clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_QSPICLKSOURCE_PLL2: /* PLL2 is used as clock source for QSPI*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_R_UPDATE);
+
+ /* QSPI clock source configuration done later after clock selection check */
+ break;
+
+
+ case RCC_QSPICLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of QSPI clock */
+ /* QSPI clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_QSPICLKSOURCE_D1HCLK:
+ /* Domain1 HCLK clock selected as QSPI kernel peripheral clock */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of QSPI clock*/
+ __HAL_RCC_QSPI_CONFIG(PeriphClkInit->QspiClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*QUADSPI*/
+
+#if defined(OCTOSPI1) || defined(OCTOSPI2)
+ /*---------------------------- OCTOSPI configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI)
+ {
+ switch (PeriphClkInit->OspiClockSelection)
+ {
+ case RCC_OSPICLKSOURCE_PLL: /* PLL is used as clock source for OSPI*/
+ /* Enable OSPI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* OSPI clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_OSPICLKSOURCE_PLL2: /* PLL2 is used as clock source for OSPI*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_R_UPDATE);
+
+ /* OSPI clock source configuration done later after clock selection check */
+ break;
+
+
+ case RCC_OSPICLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of OSPI clock */
+ /* OSPI clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_OSPICLKSOURCE_HCLK:
+ /* HCLK clock selected as OSPI kernel peripheral clock */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of OSPI clock*/
+ __HAL_RCC_OSPI_CONFIG(PeriphClkInit->OspiClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*OCTOSPI*/
+
+ /*---------------------------- SPI1/2/3 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPI123) == RCC_PERIPHCLK_SPI123)
+ {
+ switch (PeriphClkInit->Spi123ClockSelection)
+ {
+ case RCC_SPI123CLKSOURCE_PLL: /* PLL is used as clock source for SPI1/2/3 */
+ /* Enable SPI Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SPI1/2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI123CLKSOURCE_PLL2: /* PLL2 is used as clock source for SPI1/2/3 */
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* SPI1/2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI123CLKSOURCE_PLL3: /* PLL3 is used as clock source for SPI1/2/3 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ /* SPI1/2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI123CLKSOURCE_PIN:
+ /* External clock is used as source of SPI1/2/3 clock*/
+ /* SPI1/2/3 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI123CLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of SPI1/2/3 clock */
+ /* SPI1/2/3 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SPI1/2/3 clock*/
+ __HAL_RCC_SPI123_CONFIG(PeriphClkInit->Spi123ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- SPI4/5 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPI45) == RCC_PERIPHCLK_SPI45)
+ {
+ switch (PeriphClkInit->Spi45ClockSelection)
+ {
+ case RCC_SPI45CLKSOURCE_PCLK2: /* CD/D2 PCLK2 as clock source for SPI4/5 */
+ /* SPI4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI45CLKSOURCE_PLL2: /* PLL2 is used as clock source for SPI4/5 */
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+
+ /* SPI4/5 clock source configuration done later after clock selection check */
+ break;
+ case RCC_SPI45CLKSOURCE_PLL3: /* PLL3 is used as clock source for SPI4/5 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+ /* SPI4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI45CLKSOURCE_HSI:
+ /* HSI oscillator clock is used as source of SPI4/5 clock*/
+ /* SPI4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI45CLKSOURCE_CSI:
+ /* CSI oscillator clock is used as source of SPI4/5 clock */
+ /* SPI4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI45CLKSOURCE_HSE:
+ /* HSE, oscillator is used as source of SPI4/5 clock */
+ /* SPI4/5 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SPI4/5 clock*/
+ __HAL_RCC_SPI45_CONFIG(PeriphClkInit->Spi45ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- SPI6 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SPI6) == RCC_PERIPHCLK_SPI6)
+ {
+ switch (PeriphClkInit->Spi6ClockSelection)
+ {
+ case RCC_SPI6CLKSOURCE_PCLK4: /* SRD/D3 PCLK1 (PCLK4) as clock source for SPI6*/
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI6CLKSOURCE_PLL2: /* PLL2 is used as clock source for SPI6*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+ case RCC_SPI6CLKSOURCE_PLL3: /* PLL3 is used as clock source for SPI6*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI6CLKSOURCE_HSI:
+ /* HSI oscillator clock is used as source of SPI6 clock*/
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI6CLKSOURCE_CSI:
+ /* CSI oscillator clock is used as source of SPI6 clock */
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SPI6CLKSOURCE_HSE:
+ /* HSE, oscillator is used as source of SPI6 clock */
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+#if defined(RCC_SPI6CLKSOURCE_PIN)
+ case RCC_SPI6CLKSOURCE_PIN:
+ /* 2S_CKIN is used as source of SPI6 clock */
+ /* SPI6 clock source configuration done later after clock selection check */
+ break;
+#endif
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SPI6 clock*/
+ __HAL_RCC_SPI6_CONFIG(PeriphClkInit->Spi6ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+#if defined(DSI)
+ /*---------------------------- DSI configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI)
+ {
+ switch (PeriphClkInit->DsiClockSelection)
+ {
+
+ case RCC_DSICLKSOURCE_PLL2: /* PLL2 is used as clock source for DSI*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+
+ /* DSI clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_DSICLKSOURCE_PHY:
+ /* PHY is used as clock source for DSI*/
+ /* DSI clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of DSI clock*/
+ __HAL_RCC_DSI_CONFIG(PeriphClkInit->DsiClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*DSI*/
+
+#if defined(FDCAN1) || defined(FDCAN2)
+ /*---------------------------- FDCAN configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FDCAN) == RCC_PERIPHCLK_FDCAN)
+ {
+ switch (PeriphClkInit->FdcanClockSelection)
+ {
+ case RCC_FDCANCLKSOURCE_PLL: /* PLL is used as clock source for FDCAN*/
+ /* Enable FDCAN Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* FDCAN clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_FDCANCLKSOURCE_PLL2: /* PLL2 is used as clock source for FDCAN*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+
+ /* FDCAN clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_FDCANCLKSOURCE_HSE:
+ /* HSE is used as clock source for FDCAN*/
+ /* FDCAN clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of FDCAN clock*/
+ __HAL_RCC_FDCAN_CONFIG(PeriphClkInit->FdcanClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+#endif /*FDCAN1 || FDCAN2*/
+
+ /*---------------------------- FMC configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_FMC) == RCC_PERIPHCLK_FMC)
+ {
+ switch (PeriphClkInit->FmcClockSelection)
+ {
+ case RCC_FMCCLKSOURCE_PLL: /* PLL is used as clock source for FMC*/
+ /* Enable FMC Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* FMC clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_FMCCLKSOURCE_PLL2: /* PLL2 is used as clock source for FMC*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_R_UPDATE);
+
+ /* FMC clock source configuration done later after clock selection check */
+ break;
+
+
+ case RCC_FMCCLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of FMC clock */
+ /* FMC clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_FMCCLKSOURCE_HCLK:
+ /* D1/CD HCLK clock selected as FMC kernel peripheral clock */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of FMC clock*/
+ __HAL_RCC_FMC_CONFIG(PeriphClkInit->FmcClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- RTC configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
+ {
+ /* check for RTC Parameters used to output RTCCLK */
+ assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
+
+ /* Enable write access to Backup domain */
+ SET_BIT(PWR->CR1, PWR_CR1_DBP);
+
+ /* Wait for Backup domain Write protection disable */
+ tickstart = HAL_GetTick();
+
+ while ((PWR->CR1 & PWR_CR1_DBP) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
+ {
+ ret = HAL_TIMEOUT;
+ break;
+ }
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Reset the Backup domain only if the RTC Clock source selection is modified */
+ if ((RCC->BDCR & RCC_BDCR_RTCSEL) != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL))
+ {
+ /* Store the content of BDCR register before the reset of Backup Domain */
+ tmpreg = (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 = tmpreg;
+ }
+
+ /* If LSE is selected as RTC clock source (and enabled prior to Backup Domain reset), wait for LSE reactivation */
+ if (PeriphClkInit->RTCClockSelection == RCC_RTCCLKSOURCE_LSE)
+ {
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till LSE is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
+ {
+ ret = HAL_TIMEOUT;
+ break;
+ }
+ }
+ }
+
+ if (ret == HAL_OK)
+ {
+ __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+
+ /*-------------------------- USART1/6 configuration --------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART16) == RCC_PERIPHCLK_USART16)
+ {
+ switch (PeriphClkInit->Usart16ClockSelection)
+ {
+ case RCC_USART16CLKSOURCE_PCLK2: /* CD/D2 PCLK2 as clock source for USART1/6 */
+ /* USART1/6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART16CLKSOURCE_PLL2: /* PLL2 is used as clock source for USART1/6 */
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+ /* USART1/6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART16CLKSOURCE_PLL3: /* PLL3 is used as clock source for USART1/6 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+ /* USART1/6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART16CLKSOURCE_HSI:
+ /* HSI oscillator clock is used as source of USART1/6 clock */
+ /* USART1/6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART16CLKSOURCE_CSI:
+ /* CSI oscillator clock is used as source of USART1/6 clock */
+ /* USART1/6 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART16CLKSOURCE_LSE:
+ /* LSE, oscillator is used as source of USART1/6 clock */
+ /* USART1/6 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of USART1/6 clock */
+ __HAL_RCC_USART16_CONFIG(PeriphClkInit->Usart16ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*-------------------------- USART2/3/4/5/7/8 Configuration --------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART234578) == RCC_PERIPHCLK_USART234578)
+ {
+ switch (PeriphClkInit->Usart234578ClockSelection)
+ {
+ case RCC_USART234578CLKSOURCE_PCLK1: /* CD/D2 PCLK1 as clock source for USART2/3/4/5/7/8 */
+ /* USART2/3/4/5/7/8 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART234578CLKSOURCE_PLL2: /* PLL2 is used as clock source for USART2/3/4/5/7/8 */
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+ /* USART2/3/4/5/7/8 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART234578CLKSOURCE_PLL3: /* PLL3 is used as clock source for USART2/3/4/5/7/8 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+ /* USART2/3/4/5/7/8 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART234578CLKSOURCE_HSI:
+ /* HSI oscillator clock is used as source of USART2/3/4/5/7/8 clock */
+ /* USART2/3/4/5/7/8 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART234578CLKSOURCE_CSI:
+ /* CSI oscillator clock is used as source of USART2/3/4/5/7/8 clock */
+ /* USART2/3/4/5/7/8 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USART234578CLKSOURCE_LSE:
+ /* LSE, oscillator is used as source of USART2/3/4/5/7/8 clock */
+ /* USART2/3/4/5/7/8 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of USART2/3/4/5/7/8 clock */
+ __HAL_RCC_USART234578_CONFIG(PeriphClkInit->Usart234578ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*-------------------------- LPUART1 Configuration -------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1)
+ {
+ switch (PeriphClkInit->Lpuart1ClockSelection)
+ {
+ case RCC_LPUART1CLKSOURCE_PCLK4: /* SRD/D3 PCLK1 (PCLK4) as clock source for LPUART1 */
+ /* LPUART1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPUART1CLKSOURCE_PLL2: /* PLL2 is used as clock source for LPUART1 */
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+ /* LPUART1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPUART1CLKSOURCE_PLL3: /* PLL3 is used as clock source for LPUART1 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+ /* LPUART1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPUART1CLKSOURCE_HSI:
+ /* HSI oscillator clock is used as source of LPUART1 clock */
+ /* LPUART1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPUART1CLKSOURCE_CSI:
+ /* CSI oscillator clock is used as source of LPUART1 clock */
+ /* LPUART1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPUART1CLKSOURCE_LSE:
+ /* LSE, oscillator is used as source of LPUART1 clock */
+ /* LPUART1 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of LPUART1 clock */
+ __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- LPTIM1 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1)
+ {
+ switch (PeriphClkInit->Lptim1ClockSelection)
+ {
+ case RCC_LPTIM1CLKSOURCE_PCLK1: /* CD/D2 PCLK1 as clock source for LPTIM1*/
+ /* LPTIM1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM1CLKSOURCE_PLL2: /* PLL2 is used as clock source for LPTIM1*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* LPTIM1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM1CLKSOURCE_PLL3: /* PLL3 is used as clock source for LPTIM1*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE);
+
+ /* LPTIM1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM1CLKSOURCE_LSE:
+ /* External low speed OSC clock is used as source of LPTIM1 clock*/
+ /* LPTIM1 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM1CLKSOURCE_LSI:
+ /* Internal low speed OSC clock is used as source of LPTIM1 clock*/
+ /* LPTIM1 clock source configuration done later after clock selection check */
+ break;
+ case RCC_LPTIM1CLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of LPTIM1 clock */
+ /* LPTIM1 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of LPTIM1 clock*/
+ __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- LPTIM2 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2)
+ {
+ switch (PeriphClkInit->Lptim2ClockSelection)
+ {
+ case RCC_LPTIM2CLKSOURCE_PCLK4: /* SRD/D3 PCLK1 (PCLK4) as clock source for LPTIM2*/
+ /* LPTIM2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM2CLKSOURCE_PLL2: /* PLL2 is used as clock source for LPTIM2*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* LPTIM2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM2CLKSOURCE_PLL3: /* PLL3 is used as clock source for LPTIM2*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE);
+
+ /* LPTIM2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM2CLKSOURCE_LSE:
+ /* External low speed OSC clock is used as source of LPTIM2 clock*/
+ /* LPTIM2 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM2CLKSOURCE_LSI:
+ /* Internal low speed OSC clock is used as source of LPTIM2 clock*/
+ /* LPTIM2 clock source configuration done later after clock selection check */
+ break;
+ case RCC_LPTIM2CLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of LPTIM2 clock */
+ /* LPTIM2 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of LPTIM2 clock*/
+ __HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*---------------------------- LPTIM345 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM345) == RCC_PERIPHCLK_LPTIM345)
+ {
+ switch (PeriphClkInit->Lptim345ClockSelection)
+ {
+
+ case RCC_LPTIM345CLKSOURCE_PCLK4: /* SRD/D3 PCLK1 (PCLK4) as clock source for LPTIM3/4/5 */
+ /* LPTIM3/4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM345CLKSOURCE_PLL2: /* PLL2 is used as clock source for LPTIM3/4/5 */
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* LPTIM3/4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM345CLKSOURCE_PLL3: /* PLL3 is used as clock source for LPTIM3/4/5 */
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE);
+
+ /* LPTIM3/4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM345CLKSOURCE_LSE:
+ /* External low speed OSC clock is used as source of LPTIM3/4/5 clock */
+ /* LPTIM3/4/5 clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_LPTIM345CLKSOURCE_LSI:
+ /* Internal low speed OSC clock is used as source of LPTIM3/4/5 clock */
+ /* LPTIM3/4/5 clock source configuration done later after clock selection check */
+ break;
+ case RCC_LPTIM345CLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of LPTIM3/4/5 clock */
+ /* LPTIM3/4/5 clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of LPTIM3/4/5 clock */
+ __HAL_RCC_LPTIM345_CONFIG(PeriphClkInit->Lptim345ClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*------------------------------ I2C1/2/3/5* Configuration ------------------------*/
+#if defined(I2C5)
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1235) == RCC_PERIPHCLK_I2C1235)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C1235CLKSOURCE(PeriphClkInit->I2c1235ClockSelection));
+
+ if ((PeriphClkInit->I2c1235ClockSelection) == RCC_I2C1235CLKSOURCE_PLL3)
+ {
+ if (RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ __HAL_RCC_I2C1235_CONFIG(PeriphClkInit->I2c1235ClockSelection);
+
+ }
+#else
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C123) == RCC_PERIPHCLK_I2C123)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C123CLKSOURCE(PeriphClkInit->I2c123ClockSelection));
+
+ if ((PeriphClkInit->I2c123ClockSelection) == RCC_I2C123CLKSOURCE_PLL3)
+ {
+ if (RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ __HAL_RCC_I2C123_CONFIG(PeriphClkInit->I2c123ClockSelection);
+
+ }
+#endif /* I2C5 */
+
+ /*------------------------------ I2C4 Configuration ------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_I2C4CLKSOURCE(PeriphClkInit->I2c4ClockSelection));
+
+ if ((PeriphClkInit->I2c4ClockSelection) == RCC_I2C4CLKSOURCE_PLL3)
+ {
+ if (RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+
+ __HAL_RCC_I2C4_CONFIG(PeriphClkInit->I2c4ClockSelection);
+
+ }
+
+ /*---------------------------- ADC configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
+ {
+ switch (PeriphClkInit->AdcClockSelection)
+ {
+
+ case RCC_ADCCLKSOURCE_PLL2: /* PLL2 is used as clock source for ADC*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ /* ADC clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_ADCCLKSOURCE_PLL3: /* PLL3 is used as clock source for ADC*/
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE);
+
+ /* ADC clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_ADCCLKSOURCE_CLKP:
+ /* HSI, HSE, or CSI oscillator is used as source of ADC clock */
+ /* ADC clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of ADC clock*/
+ __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ /*------------------------------ USB Configuration -------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB)
+ {
+
+ switch (PeriphClkInit->UsbClockSelection)
+ {
+ case RCC_USBCLKSOURCE_PLL: /* PLL is used as clock source for USB*/
+ /* Enable USB Clock output generated form System USB . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* USB clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USBCLKSOURCE_PLL3: /* PLL3 is used as clock source for USB*/
+
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+
+ /* USB clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_USBCLKSOURCE_HSI48:
+ /* HSI48 oscillator is used as source of USB clock */
+ /* USB clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of USB clock*/
+ __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+
+ }
+
+ /*------------------------------------- SDMMC Configuration ------------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC) == RCC_PERIPHCLK_SDMMC)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SDMMC(PeriphClkInit->SdmmcClockSelection));
+
+ switch (PeriphClkInit->SdmmcClockSelection)
+ {
+ case RCC_SDMMCCLKSOURCE_PLL: /* PLL is used as clock source for SDMMC*/
+ /* Enable SDMMC Clock output generated form System PLL . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* SDMMC clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_SDMMCCLKSOURCE_PLL2: /* PLL2 is used as clock source for SDMMC*/
+
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_R_UPDATE);
+
+ /* SDMMC clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of SDMMC clock*/
+ __HAL_RCC_SDMMC_CONFIG(PeriphClkInit->SdmmcClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+#if defined(LTDC)
+ /*-------------------------------------- LTDC Configuration -----------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)
+ {
+ if (RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+ }
+#endif /* LTDC */
+
+ /*------------------------------ RNG Configuration -------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG)
+ {
+
+ switch (PeriphClkInit->RngClockSelection)
+ {
+ case RCC_RNGCLKSOURCE_PLL: /* PLL is used as clock source for RNG*/
+ /* Enable RNG Clock output generated form System RNG . */
+ __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL1_DIVQ);
+
+ /* RNG clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_RNGCLKSOURCE_LSE: /* LSE is used as clock source for RNG*/
+
+ /* RNG clock source configuration done later after clock selection check */
+ break;
+
+ case RCC_RNGCLKSOURCE_LSI: /* LSI is used as clock source for RNG*/
+
+ /* RNG clock source configuration done later after clock selection check */
+ break;
+ case RCC_RNGCLKSOURCE_HSI48:
+ /* HSI48 oscillator is used as source of RNG clock */
+ /* RNG clock source configuration done later after clock selection check */
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ if (ret == HAL_OK)
+ {
+ /* Set the source of RNG clock*/
+ __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection);
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+
+ }
+
+ /*------------------------------ SWPMI1 Configuration ------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection));
+
+ /* Configure the SWPMI1 interface clock source */
+ __HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection);
+ }
+#if defined(HRTIM1)
+ /*------------------------------ HRTIM1 clock Configuration ----------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_HRTIM1) == RCC_PERIPHCLK_HRTIM1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_HRTIM1CLKSOURCE(PeriphClkInit->Hrtim1ClockSelection));
+
+ /* Configure the HRTIM1 clock source */
+ __HAL_RCC_HRTIM1_CONFIG(PeriphClkInit->Hrtim1ClockSelection);
+ }
+#endif /*HRTIM1*/
+ /*------------------------------ DFSDM1 Configuration ------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection));
+
+ /* Configure the DFSDM1 interface clock source */
+ __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection);
+ }
+
+#if defined(DFSDM2_BASE)
+ /*------------------------------ DFSDM2 Configuration ------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM2) == RCC_PERIPHCLK_DFSDM2)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_DFSDM2CLKSOURCE(PeriphClkInit->Dfsdm2ClockSelection));
+
+ /* Configure the DFSDM2 interface clock source */
+ __HAL_RCC_DFSDM2_CONFIG(PeriphClkInit->Dfsdm2ClockSelection);
+ }
+#endif /* DFSDM2 */
+
+ /*------------------------------------ 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);
+ }
+
+ /*------------------------------------ CKPER configuration --------------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CKPER) == RCC_PERIPHCLK_CKPER)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_CLKPSOURCE(PeriphClkInit->CkperClockSelection));
+
+ /* Configure the CKPER clock source */
+ __HAL_RCC_CLKP_CONFIG(PeriphClkInit->CkperClockSelection);
+ }
+
+ /*------------------------------ CEC Configuration ------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_CEC) == RCC_PERIPHCLK_CEC)
+ {
+ /* Check the parameters */
+ assert_param(IS_RCC_CECCLKSOURCE(PeriphClkInit->CecClockSelection));
+
+ /* Configure the CEC interface clock source */
+ __HAL_RCC_CEC_CONFIG(PeriphClkInit->CecClockSelection);
+ }
+
+ /*---------------------------- PLL2 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLL2_DIVP) == RCC_PERIPHCLK_PLL2_DIVP)
+ {
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_P_UPDATE);
+
+ if (ret == HAL_OK)
+ {
+ /*Nothing to do*/
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLL2_DIVQ) == RCC_PERIPHCLK_PLL2_DIVQ)
+ {
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_Q_UPDATE);
+
+ if (ret == HAL_OK)
+ {
+ /*Nothing to do*/
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLL2_DIVR) == RCC_PERIPHCLK_PLL2_DIVR)
+ {
+ ret = RCCEx_PLL2_Config(&(PeriphClkInit->PLL2), DIVIDER_R_UPDATE);
+
+ if (ret == HAL_OK)
+ {
+ /*Nothing to do*/
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+
+ /*---------------------------- PLL3 configuration -------------------------------*/
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLL3_DIVP) == RCC_PERIPHCLK_PLL3_DIVP)
+ {
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_P_UPDATE);
+
+ if (ret == HAL_OK)
+ {
+ /*Nothing to do*/
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLL3_DIVQ) == RCC_PERIPHCLK_PLL3_DIVQ)
+ {
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_Q_UPDATE);
+
+ if (ret == HAL_OK)
+ {
+ /*Nothing to do*/
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+
+ if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_PLL3_DIVR) == RCC_PERIPHCLK_PLL3_DIVR)
+ {
+ ret = RCCEx_PLL3_Config(&(PeriphClkInit->PLL3), DIVIDER_R_UPDATE);
+
+ if (ret == HAL_OK)
+ {
+ /*Nothing to do*/
+ }
+ else
+ {
+ /* set overall return value */
+ status = ret;
+ }
+ }
+
+ if (status == HAL_OK)
+ {
+ return HAL_OK;
+ }
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers.
+ * @param PeriphClkInit: pointer to an RCC_PeriphCLKInitTypeDef structure that
+ * returns the configuration information for the Extended Peripherals clocks :
+ * (SDMMC, CKPER, FMC, QSPI*, OSPI*, DSI*, SPI45, SPDIF, DFSDM1, DFSDM2*, FDCAN, SWPMI, SAI23*, SAI1, SPI123,
+ * USART234578, USART16, RNG, HRTIM1*, I2C123 (I2C1235*), USB, CEC, LPTIM1, LPUART1, I2C4, LPTIM2, LPTIM345, ADC.
+ * SAI4A*, SAI4B*, SPI6, RTC, TIM).
+ * @retval None
+ *
+ * (*) : Available on some STM32H7 lines only.
+ */
+void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
+{
+ /* Set all possible values for the extended clock type parameter------------*/
+ PeriphClkInit->PeriphClockSelection =
+ RCC_PERIPHCLK_USART16 | RCC_PERIPHCLK_USART234578 | RCC_PERIPHCLK_LPUART1 |
+ RCC_PERIPHCLK_I2C4 | RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_LPTIM345 |
+ RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SPI123 | RCC_PERIPHCLK_SPI45 | RCC_PERIPHCLK_SPI6 |
+ RCC_PERIPHCLK_FDCAN | RCC_PERIPHCLK_SDMMC | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_USB |
+ RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | RCC_PERIPHCLK_RTC |
+ RCC_PERIPHCLK_CEC | RCC_PERIPHCLK_FMC | RCC_PERIPHCLK_SPDIFRX | RCC_PERIPHCLK_TIM |
+ RCC_PERIPHCLK_CKPER;
+
+#if defined(I2C5)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2C1235;
+#else
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2C123;
+#endif /*I2C5*/
+#if defined(RCC_CDCCIP1R_SAI2ASEL)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SAI2A;
+#endif /* RCC_CDCCIP1R_SAI2ASEL */
+#if defined(RCC_CDCCIP1R_SAI2BSEL)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SAI2B;
+#endif /* RCC_CDCCIP1R_SAI2BSEL */
+#if defined(SAI3)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SAI23;
+#endif /* SAI3 */
+#if defined(SAI4)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SAI4A;
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_SAI4B;
+#endif /* SAI4 */
+#if defined(DFSDM2_BASE)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_DFSDM2;
+#endif /* DFSDM2 */
+#if defined(QUADSPI)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_QSPI;
+#endif /* QUADSPI */
+#if defined(OCTOSPI1) || defined(OCTOSPI2)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_OSPI;
+#endif /* OCTOSPI1 || OCTOSPI2 */
+#if defined(HRTIM1)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_HRTIM1;
+#endif /* HRTIM1 */
+#if defined(LTDC)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_LTDC;
+#endif /* LTDC */
+#if defined(DSI)
+ PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_DSI;
+#endif /* DSI */
+
+ /* Get the PLL3 Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLL3.PLL3M = (uint32_t)((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM3) >> RCC_PLLCKSELR_DIVM3_Pos);
+ PeriphClkInit->PLL3.PLL3N = (uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_N3) >> RCC_PLL3DIVR_N3_Pos) + 1U;
+ PeriphClkInit->PLL3.PLL3R = (uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_R3) >> RCC_PLL3DIVR_R3_Pos) + 1U;
+ PeriphClkInit->PLL3.PLL3P = (uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_P3) >> RCC_PLL3DIVR_P3_Pos) + 1U;
+ PeriphClkInit->PLL3.PLL3Q = (uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_Q3) >> RCC_PLL3DIVR_Q3_Pos) + 1U;
+ PeriphClkInit->PLL3.PLL3RGE = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLL3RGE) >> RCC_PLLCFGR_PLL3RGE_Pos);
+ PeriphClkInit->PLL3.PLL3VCOSEL = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLL3VCOSEL) >> RCC_PLLCFGR_PLL3VCOSEL_Pos);
+
+ /* Get the PLL2 Clock configuration -----------------------------------------------*/
+ PeriphClkInit->PLL2.PLL2M = (uint32_t)((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM2) >> RCC_PLLCKSELR_DIVM2_Pos);
+ PeriphClkInit->PLL2.PLL2N = (uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_N2) >> RCC_PLL2DIVR_N2_Pos) + 1U;
+ PeriphClkInit->PLL2.PLL2R = (uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_R2) >> RCC_PLL2DIVR_R2_Pos) + 1U;
+ PeriphClkInit->PLL2.PLL2P = (uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_P2) >> RCC_PLL2DIVR_P2_Pos) + 1U;
+ PeriphClkInit->PLL2.PLL2Q = (uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_Q2) >> RCC_PLL2DIVR_Q2_Pos) + 1U;
+ PeriphClkInit->PLL2.PLL2RGE = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLL2RGE) >> RCC_PLLCFGR_PLL2RGE_Pos);
+ PeriphClkInit->PLL2.PLL2VCOSEL = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLL2VCOSEL) >> RCC_PLLCFGR_PLL2VCOSEL_Pos);
+
+ /* Get the USART1 configuration --------------------------------------------*/
+ PeriphClkInit->Usart16ClockSelection = __HAL_RCC_GET_USART16_SOURCE();
+ /* Get the USART2/3/4/5/7/8 clock source -----------------------------------*/
+ PeriphClkInit->Usart234578ClockSelection = __HAL_RCC_GET_USART234578_SOURCE();
+ /* Get the LPUART1 clock source --------------------------------------------*/
+ PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE();
+#if defined(I2C5)
+ /* Get the I2C1/2/3/5 clock source -----------------------------------------*/
+ PeriphClkInit->I2c1235ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
+#else
+ /* Get the I2C1/2/3 clock source -------------------------------------------*/
+ PeriphClkInit->I2c123ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
+#endif /*I2C5*/
+ /* Get the LPTIM1 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
+ /* Get the LPTIM2 clock source ---------------------------------------------*/
+ PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE();
+ /* Get the LPTIM3/4/5 clock source -----------------------------------------*/
+ PeriphClkInit->Lptim345ClockSelection = __HAL_RCC_GET_LPTIM345_SOURCE();
+ /* Get the SAI1 clock source -----------------------------------------------*/
+ PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();
+#if defined(SAI3)
+ /* Get the SAI2/3 clock source ---------------------------------------------*/
+ PeriphClkInit->Sai23ClockSelection = __HAL_RCC_GET_SAI23_SOURCE();
+#endif /*SAI3*/
+#if defined(RCC_CDCCIP1R_SAI2ASEL_0)
+ /* Get the SAI2A clock source ---------------------------------------------*/
+ PeriphClkInit->Sai2AClockSelection = __HAL_RCC_GET_SAI2A_SOURCE();
+#endif /*SAI2A*/
+#if defined(RCC_CDCCIP1R_SAI2BSEL_0)
+ /* Get the SAI2B clock source ---------------------------------------------*/
+ PeriphClkInit->Sai2BClockSelection = __HAL_RCC_GET_SAI2B_SOURCE();
+#endif /*SAI2B*/
+#if defined(SAI4)
+ /* Get the SAI4A clock source ----------------------------------------------*/
+ PeriphClkInit->Sai4AClockSelection = __HAL_RCC_GET_SAI4A_SOURCE();
+ /* Get the SAI4B clock source ----------------------------------------------*/
+ PeriphClkInit->Sai4BClockSelection = __HAL_RCC_GET_SAI4B_SOURCE();
+#endif /*SAI4*/
+ /* Get the RTC clock source ------------------------------------------------*/
+ PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
+ /* Get the USB clock source ------------------------------------------------*/
+ PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
+ /* Get the SDMMC clock source ----------------------------------------------*/
+ PeriphClkInit->SdmmcClockSelection = __HAL_RCC_GET_SDMMC_SOURCE();
+ /* Get the RNG clock source ------------------------------------------------*/
+ PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE();
+#if defined(HRTIM1)
+ /* Get the HRTIM1 clock source ---------------------------------------------*/
+ PeriphClkInit->Hrtim1ClockSelection = __HAL_RCC_GET_HRTIM1_SOURCE();
+#endif /* HRTIM1 */
+ /* Get the ADC clock source ------------------------------------------------*/
+ PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
+ /* Get the SWPMI1 clock source ---------------------------------------------*/
+ PeriphClkInit->Swpmi1ClockSelection = __HAL_RCC_GET_SWPMI1_SOURCE();
+ /* Get the DFSDM1 clock source ---------------------------------------------*/
+ PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE();
+#if defined(DFSDM2_BASE)
+ /* Get the DFSDM2 clock source ---------------------------------------------*/
+ PeriphClkInit->Dfsdm2ClockSelection = __HAL_RCC_GET_DFSDM2_SOURCE();
+#endif /* DFSDM2 */
+ /* Get the SPDIFRX clock source --------------------------------------------*/
+ PeriphClkInit->SpdifrxClockSelection = __HAL_RCC_GET_SPDIFRX_SOURCE();
+ /* Get the SPI1/2/3 clock source -------------------------------------------*/
+ PeriphClkInit->Spi123ClockSelection = __HAL_RCC_GET_SPI123_SOURCE();
+ /* Get the SPI4/5 clock source ---------------------------------------------*/
+ PeriphClkInit->Spi45ClockSelection = __HAL_RCC_GET_SPI45_SOURCE();
+ /* Get the SPI6 clock source -----------------------------------------------*/
+ PeriphClkInit->Spi6ClockSelection = __HAL_RCC_GET_SPI6_SOURCE();
+ /* Get the FDCAN clock source ----------------------------------------------*/
+ PeriphClkInit->FdcanClockSelection = __HAL_RCC_GET_FDCAN_SOURCE();
+ /* Get the CEC clock source ------------------------------------------------*/
+ PeriphClkInit->CecClockSelection = __HAL_RCC_GET_CEC_SOURCE();
+ /* Get the FMC clock source ------------------------------------------------*/
+ PeriphClkInit->FmcClockSelection = __HAL_RCC_GET_FMC_SOURCE();
+#if defined(QUADSPI)
+ /* Get the QSPI clock source -----------------------------------------------*/
+ PeriphClkInit->QspiClockSelection = __HAL_RCC_GET_QSPI_SOURCE();
+#endif /* QUADSPI */
+#if defined(OCTOSPI1) || defined(OCTOSPI2)
+ /* Get the OSPI clock source -----------------------------------------------*/
+ PeriphClkInit->OspiClockSelection = __HAL_RCC_GET_OSPI_SOURCE();
+#endif /* OCTOSPI1 || OCTOSPI2 */
+
+#if defined(DSI)
+ /* Get the DSI clock source ------------------------------------------------*/
+ PeriphClkInit->DsiClockSelection = __HAL_RCC_GET_DSI_SOURCE();
+#endif /*DSI*/
+
+ /* Get the CKPER clock source ----------------------------------------------*/
+ PeriphClkInit->CkperClockSelection = __HAL_RCC_GET_CLKP_SOURCE();
+
+ /* Get the TIM Prescaler configuration -------------------------------------*/
+ if ((RCC->CFGR & RCC_CFGR_TIMPRE) == 0U)
+ {
+ 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_SAI23 : SAI2/3 peripheral clock (*)
+ * @arg RCC_PERIPHCLK_SAI2A : SAI2A peripheral clock (*)
+ * @arg RCC_PERIPHCLK_SAI2B : SAI2B peripheral clock (*)
+ * @arg RCC_PERIPHCLK_SAI4A : SAI4A peripheral clock (*)
+ * @arg RCC_PERIPHCLK_SAI4B : SAI4B peripheral clock (*)
+ * @arg RCC_PERIPHCLK_SPI123: SPI1/2/3 peripheral clock
+ * @arg RCC_PERIPHCLK_ADC : ADC peripheral clock
+ * @arg RCC_PERIPHCLK_SDMMC : SDMMC peripheral clock
+ * @arg RCC_PERIPHCLK_SPI6 : SPI6 peripheral clock
+ * @retval Frequency in KHz
+ *
+ * (*) : Available on some STM32H7 lines only.
+ */
+uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint64_t PeriphClk)
+{
+ PLL1_ClocksTypeDef pll1_clocks;
+ PLL2_ClocksTypeDef pll2_clocks;
+ PLL3_ClocksTypeDef pll3_clocks;
+
+ /* This variable is used to store the clock frequency (value in Hz) */
+ uint32_t frequency;
+ /* This variable is used to store the SAI and CKP clock source */
+ uint32_t saiclocksource;
+ uint32_t ckpclocksource;
+ uint32_t srcclk;
+
+ if (PeriphClk == RCC_PERIPHCLK_SAI1)
+ {
+
+ saiclocksource = __HAL_RCC_GET_SAI1_SOURCE();
+
+ switch (saiclocksource)
+ {
+ case RCC_SAI1CLKSOURCE_PLL: /* PLL1 is the clock source for SAI1 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SAI1CLKSOURCE_PLL2: /* PLL2 is the clock source for SAI1 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI1CLKSOURCE_PLL3: /* PLL3 is the clock source for SAI1 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI1CLKSOURCE_CLKP: /* CKPER is the clock source for SAI1*/
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ case (RCC_SAI1CLKSOURCE_PIN): /* External clock is the clock source for SAI1 */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+
+#if defined(SAI3)
+ else if (PeriphClk == RCC_PERIPHCLK_SAI23)
+ {
+
+ saiclocksource = __HAL_RCC_GET_SAI23_SOURCE();
+
+ switch (saiclocksource)
+ {
+ case RCC_SAI23CLKSOURCE_PLL: /* PLL1 is the clock source for SAI2/3 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SAI23CLKSOURCE_PLL2: /* PLL2 is the clock source for SAI2/3 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI23CLKSOURCE_PLL3: /* PLL3 is the clock source for SAI2/3 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI23CLKSOURCE_CLKP: /* CKPER is the clock source for SAI2/3 */
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ case (RCC_SAI23CLKSOURCE_PIN): /* External clock is the clock source for SAI2/3 */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+#endif /* SAI3 */
+
+#if defined(RCC_CDCCIP1R_SAI2ASEL)
+
+ else if (PeriphClk == RCC_PERIPHCLK_SAI2A)
+ {
+ saiclocksource = __HAL_RCC_GET_SAI2A_SOURCE();
+
+ switch (saiclocksource)
+ {
+ case RCC_SAI2ACLKSOURCE_PLL: /* PLL1 is the clock source for SAI2A */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SAI2ACLKSOURCE_PLL2: /* PLLI2 is the clock source for SAI2A */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI2ACLKSOURCE_PLL3: /* PLLI3 is the clock source for SAI2A */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI2ACLKSOURCE_CLKP: /* CKPER is the clock source for SAI2A */
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ case (RCC_SAI2ACLKSOURCE_PIN): /* External clock is the clock source for SAI2A */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+
+ }
+#endif
+
+#if defined(RCC_CDCCIP1R_SAI2BSEL_0)
+ else if (PeriphClk == RCC_PERIPHCLK_SAI2B)
+ {
+
+ saiclocksource = __HAL_RCC_GET_SAI2B_SOURCE();
+
+ switch (saiclocksource)
+ {
+ case RCC_SAI2BCLKSOURCE_PLL: /* PLL1 is the clock source for SAI2B */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SAI2BCLKSOURCE_PLL2: /* PLLI2 is the clock source for SAI2B */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI2BCLKSOURCE_PLL3: /* PLLI3 is the clock source for SAI2B */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI2BCLKSOURCE_CLKP: /* CKPER is the clock source for SAI2B*/
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+ break;
+ }
+
+ case (RCC_SAI2BCLKSOURCE_PIN): /* External clock is the clock source for SAI2B */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+#endif
+
+#if defined(SAI4)
+ else if (PeriphClk == RCC_PERIPHCLK_SAI4A)
+ {
+
+ saiclocksource = __HAL_RCC_GET_SAI4A_SOURCE();
+
+ switch (saiclocksource)
+ {
+ case RCC_SAI4ACLKSOURCE_PLL: /* PLL1 is the clock source for SAI4A */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SAI4ACLKSOURCE_PLL2: /* PLLI2 is the clock source for SAI4A */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI4ACLKSOURCE_PLL3: /* PLLI3 is the clock source for SAI4A */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI4ACLKSOURCE_CLKP: /* CKPER is the clock source for SAI4A*/
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ case RCC_SAI4ACLKSOURCE_PIN: /* External clock is the clock source for SAI4A */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+
+ else if (PeriphClk == RCC_PERIPHCLK_SAI4B)
+ {
+
+ saiclocksource = __HAL_RCC_GET_SAI4B_SOURCE();
+
+ switch (saiclocksource)
+ {
+ case RCC_SAI4BCLKSOURCE_PLL: /* PLL1 is the clock source for SAI4B */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SAI4BCLKSOURCE_PLL2: /* PLLI2 is the clock source for SAI4B */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI4BCLKSOURCE_PLL3: /* PLLI3 is the clock source for SAI4B */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SAI4BCLKSOURCE_CLKP: /* CKPER is the clock source for SAI4B*/
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ case RCC_SAI4BCLKSOURCE_PIN: /* External clock is the clock source for SAI4B */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+#endif /*SAI4*/
+ else if (PeriphClk == RCC_PERIPHCLK_SPI123)
+ {
+ /* Get SPI1/2/3 clock source */
+ srcclk = __HAL_RCC_GET_SPI123_SOURCE();
+
+ switch (srcclk)
+ {
+ case RCC_SPI123CLKSOURCE_PLL: /* PLL1 is the clock source for SPI123 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI123CLKSOURCE_PLL2: /* PLL2 is the clock source for SPI123 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SPI123CLKSOURCE_PLL3: /* PLL3 is the clock source for SPI123 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_SPI123CLKSOURCE_CLKP: /* CKPER is the clock source for SPI123 */
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ case (RCC_SPI123CLKSOURCE_PIN): /* External clock is the clock source for I2S */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_SPI45)
+ {
+ /* Get SPI45 clock source */
+ srcclk = __HAL_RCC_GET_SPI45_SOURCE();
+ switch (srcclk)
+ {
+ case RCC_SPI45CLKSOURCE_PCLK2: /* CD/D2 PCLK2 is the clock source for SPI4/5 */
+ {
+ frequency = HAL_RCC_GetPCLK1Freq();
+ break;
+ }
+ case RCC_SPI45CLKSOURCE_PLL2: /* PLL2 is the clock source for SPI45 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI45CLKSOURCE_PLL3: /* PLL3 is the clock source for SPI45 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI45CLKSOURCE_HSI: /* HSI is the clock source for SPI45 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
+ {
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI45CLKSOURCE_CSI: /* CSI is the clock source for SPI45 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY))
+ {
+ frequency = CSI_VALUE;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI45CLKSOURCE_HSE: /* HSE is the clock source for SPI45 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
+ {
+ frequency = HSE_VALUE;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_ADC)
+ {
+ /* Get ADC clock source */
+ srcclk = __HAL_RCC_GET_ADC_SOURCE();
+
+ switch (srcclk)
+ {
+ case RCC_ADCCLKSOURCE_PLL2:
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_P_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_ADCCLKSOURCE_PLL3:
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_R_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ case RCC_ADCCLKSOURCE_CLKP:
+ {
+
+ ckpclocksource = __HAL_RCC_GET_CLKP_SOURCE();
+
+ if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSI))
+ {
+ /* In Case the CKPER Source is HSI */
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY)) && (ckpclocksource == RCC_CLKPSOURCE_CSI))
+ {
+ /* In Case the CKPER Source is CSI */
+ frequency = CSI_VALUE;
+ }
+
+ else if ((HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) && (ckpclocksource == RCC_CLKPSOURCE_HSE))
+ {
+ /* In Case the CKPER Source is HSE */
+ frequency = HSE_VALUE;
+ }
+
+ else
+ {
+ /* In Case the CKPER is disabled*/
+ frequency = 0;
+ }
+
+ break;
+ }
+
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_SDMMC)
+ {
+ /* Get SDMMC clock source */
+ srcclk = __HAL_RCC_GET_SDMMC_SOURCE();
+
+ switch (srcclk)
+ {
+ case RCC_SDMMCCLKSOURCE_PLL: /* PLL1 is the clock source for SDMMC */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SDMMCCLKSOURCE_PLL2: /* PLL2 is the clock source for SDMMC */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_R_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_SPI6)
+ {
+ /* Get SPI6 clock source */
+ srcclk = __HAL_RCC_GET_SPI6_SOURCE();
+
+ switch (srcclk)
+ {
+ case RCC_SPI6CLKSOURCE_D3PCLK1: /* D3PCLK1 (PCLK4) is the clock source for SPI6 */
+ {
+ frequency = HAL_RCCEx_GetD3PCLK1Freq();
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_PLL2: /* PLL2 is the clock source for SPI6 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_PLL3: /* PLL3 is the clock source for SPI6 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3RDY))
+ {
+ HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
+ frequency = pll3_clocks.PLL3_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_HSI: /* HSI is the clock source for SPI6 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
+ {
+ frequency = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_CSI: /* CSI is the clock source for SPI6 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_CSIRDY))
+ {
+ frequency = CSI_VALUE;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_SPI6CLKSOURCE_HSE: /* HSE is the clock source for SPI6 */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
+ {
+ frequency = HSE_VALUE;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+#if defined(RCC_SPI6CLKSOURCE_PIN)
+ case RCC_SPI6CLKSOURCE_PIN: /* External clock is the clock source for SPI6 */
+ {
+ frequency = EXTERNAL_CLOCK_VALUE;
+ break;
+ }
+#endif /* RCC_SPI6CLKSOURCE_PIN */
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+ else if (PeriphClk == RCC_PERIPHCLK_FDCAN)
+ {
+ /* Get FDCAN clock source */
+ srcclk = __HAL_RCC_GET_FDCAN_SOURCE();
+
+ switch (srcclk)
+ {
+ case RCC_FDCANCLKSOURCE_HSE: /* HSE is the clock source for FDCAN */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
+ {
+ frequency = HSE_VALUE;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_FDCANCLKSOURCE_PLL: /* PLL is the clock source for FDCAN */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL1RDY))
+ {
+ HAL_RCCEx_GetPLL1ClockFreq(&pll1_clocks);
+ frequency = pll1_clocks.PLL1_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ case RCC_FDCANCLKSOURCE_PLL2: /* PLL2 is the clock source for FDCAN */
+ {
+ if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2RDY))
+ {
+ HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
+ frequency = pll2_clocks.PLL2_Q_Frequency;
+ }
+ else
+ {
+ frequency = 0;
+ }
+ break;
+ }
+ default :
+ {
+ frequency = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ frequency = 0;
+ }
+
+ return frequency;
+}
+
+
+/**
+ * @brief Returns the D1PCLK1 frequency
+ * @note Each time D1PCLK1 changes, this function must be called to update the
+ * right D1PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
+ * @retval D1PCLK1 frequency
+ */
+uint32_t HAL_RCCEx_GetD1PCLK1Freq(void)
+{
+#if defined(RCC_D1CFGR_D1PPRE)
+ /* Get HCLK source and Compute D1PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> (D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1PPRE) >> RCC_D1CFGR_D1PPRE_Pos] & 0x1FU));
+#else
+ /* Get HCLK source and Compute D1PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> (D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDPPRE) >> RCC_CDCFGR1_CDPPRE_Pos] & 0x1FU));
+#endif
+}
+
+/**
+ * @brief Returns the D3PCLK1 frequency
+ * @note Each time D3PCLK1 changes, this function must be called to update the
+ * right D3PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
+ * @retval D3PCLK1 frequency
+ */
+uint32_t HAL_RCCEx_GetD3PCLK1Freq(void)
+{
+#if defined(RCC_D3CFGR_D3PPRE)
+ /* Get HCLK source and Compute D3PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> (D1CorePrescTable[(RCC->D3CFGR & RCC_D3CFGR_D3PPRE) >> RCC_D3CFGR_D3PPRE_Pos] & 0x1FU));
+#else
+ /* Get HCLK source and Compute D3PCLK1 frequency ---------------------------*/
+ return (HAL_RCC_GetHCLKFreq() >> (D1CorePrescTable[(RCC->SRDCFGR & RCC_SRDCFGR_SRDPPRE) >> RCC_SRDCFGR_SRDPPRE_Pos] & 0x1FU));
+#endif
+}
+/**
+* @brief Returns the PLL2 clock frequencies :PLL2_P_Frequency,PLL2_R_Frequency and PLL2_Q_Frequency
+ * @note The PLL2 clock frequencies 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 The function returns values based on HSE_VALUE, HSI_VALUE or CSI Value multiplied/divided by the PLL factors.
+ * @note This function can be used by the user application to compute the
+ * baud-rate for the communication peripherals or configure other parameters.
+ *
+ * @note Each time PLL2CLK changes, this function must be called to update the
+ * right PLL2CLK value. Otherwise, any configuration based on this function will be incorrect.
+ * @param PLL2_Clocks structure.
+ * @retval None
+ */
+void HAL_RCCEx_GetPLL2ClockFreq(PLL2_ClocksTypeDef *PLL2_Clocks)
+{
+ uint32_t pllsource, pll2m, pll2fracen, hsivalue;
+ float_t fracn2, pll2vco;
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLL2M) * PLL2N
+ PLL2xCLK = PLL2_VCO / PLL2x
+ */
+ pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
+ pll2m = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM2) >> 12);
+ pll2fracen = (RCC->PLLCFGR & RCC_PLLCFGR_PLL2FRACEN) >> RCC_PLLCFGR_PLL2FRACEN_Pos;
+ fracn2 = (float_t)(uint32_t)(pll2fracen * ((RCC->PLL2FRACR & RCC_PLL2FRACR_FRACN2) >> 3));
+
+ if (pll2m != 0U)
+ {
+ switch (pllsource)
+ {
+
+ case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ hsivalue = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ pll2vco = ((float_t)hsivalue / (float_t)pll2m) * ((float_t)(uint32_t)(RCC->PLL2DIVR & RCC_PLL2DIVR_N2) + (fracn2 / (float_t)0x2000) + (float_t)1);
+ }
+ else
+ {
+ pll2vco = ((float_t)HSI_VALUE / (float_t)pll2m) * ((float_t)(uint32_t)(RCC->PLL2DIVR & RCC_PLL2DIVR_N2) + (fracn2 / (float_t)0x2000) + (float_t)1);
+ }
+ break;
+
+ case RCC_PLLSOURCE_CSI: /* CSI used as PLL clock source */
+ pll2vco = ((float_t)CSI_VALUE / (float_t)pll2m) * ((float_t)(uint32_t)(RCC->PLL2DIVR & RCC_PLL2DIVR_N2) + (fracn2 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ pll2vco = ((float_t)HSE_VALUE / (float_t)pll2m) * ((float_t)(uint32_t)(RCC->PLL2DIVR & RCC_PLL2DIVR_N2) + (fracn2 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ default:
+ pll2vco = ((float_t)CSI_VALUE / (float_t)pll2m) * ((float_t)(uint32_t)(RCC->PLL2DIVR & RCC_PLL2DIVR_N2) + (fracn2 / (float_t)0x2000) + (float_t)1);
+ break;
+ }
+ PLL2_Clocks->PLL2_P_Frequency = (uint32_t)(float_t)(pll2vco / ((float_t)(uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_P2) >> 9) + (float_t)1)) ;
+ PLL2_Clocks->PLL2_Q_Frequency = (uint32_t)(float_t)(pll2vco / ((float_t)(uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_Q2) >> 16) + (float_t)1)) ;
+ PLL2_Clocks->PLL2_R_Frequency = (uint32_t)(float_t)(pll2vco / ((float_t)(uint32_t)((RCC->PLL2DIVR & RCC_PLL2DIVR_R2) >> 24) + (float_t)1)) ;
+ }
+ else
+ {
+ PLL2_Clocks->PLL2_P_Frequency = 0U;
+ PLL2_Clocks->PLL2_Q_Frequency = 0U;
+ PLL2_Clocks->PLL2_R_Frequency = 0U;
+ }
+}
+
+/**
+* @brief Returns the PLL3 clock frequencies :PLL3_P_Frequency,PLL3_R_Frequency and PLL3_Q_Frequency
+ * @note The PLL3 clock frequencies 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 The function returns values based on HSE_VALUE, HSI_VALUE or CSI Value multiplied/divided by the PLL factors.
+ * @note This function can be used by the user application to compute the
+ * baud-rate for the communication peripherals or configure other parameters.
+ *
+ * @note Each time PLL3CLK changes, this function must be called to update the
+ * right PLL3CLK value. Otherwise, any configuration based on this function will be incorrect.
+ * @param PLL3_Clocks structure.
+ * @retval None
+ */
+void HAL_RCCEx_GetPLL3ClockFreq(PLL3_ClocksTypeDef *PLL3_Clocks)
+{
+ uint32_t pllsource, pll3m, pll3fracen, hsivalue;
+ float_t fracn3, pll3vco;
+
+ /* PLL3_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLL3M) * PLL3N
+ PLL3xCLK = PLL3_VCO / PLLxR
+ */
+ pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
+ pll3m = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM3) >> 20) ;
+ pll3fracen = (RCC->PLLCFGR & RCC_PLLCFGR_PLL3FRACEN) >> RCC_PLLCFGR_PLL3FRACEN_Pos;
+ fracn3 = (float_t)(uint32_t)(pll3fracen * ((RCC->PLL3FRACR & RCC_PLL3FRACR_FRACN3) >> 3));
+
+ if (pll3m != 0U)
+ {
+ switch (pllsource)
+ {
+ case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ hsivalue = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ pll3vco = ((float_t)hsivalue / (float_t)pll3m) * ((float_t)(uint32_t)(RCC->PLL3DIVR & RCC_PLL3DIVR_N3) + (fracn3 / (float_t)0x2000) + (float_t)1);
+ }
+ else
+ {
+ pll3vco = ((float_t)HSI_VALUE / (float_t)pll3m) * ((float_t)(uint32_t)(RCC->PLL3DIVR & RCC_PLL3DIVR_N3) + (fracn3 / (float_t)0x2000) + (float_t)1);
+ }
+ break;
+ case RCC_PLLSOURCE_CSI: /* CSI used as PLL clock source */
+ pll3vco = ((float_t)CSI_VALUE / (float_t)pll3m) * ((float_t)(uint32_t)(RCC->PLL3DIVR & RCC_PLL3DIVR_N3) + (fracn3 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ pll3vco = ((float_t)HSE_VALUE / (float_t)pll3m) * ((float_t)(uint32_t)(RCC->PLL3DIVR & RCC_PLL3DIVR_N3) + (fracn3 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ default:
+ pll3vco = ((float_t)CSI_VALUE / (float_t)pll3m) * ((float_t)(uint32_t)(RCC->PLL3DIVR & RCC_PLL3DIVR_N3) + (fracn3 / (float_t)0x2000) + (float_t)1);
+ break;
+ }
+ PLL3_Clocks->PLL3_P_Frequency = (uint32_t)(float_t)(pll3vco / ((float_t)(uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_P3) >> 9) + (float_t)1)) ;
+ PLL3_Clocks->PLL3_Q_Frequency = (uint32_t)(float_t)(pll3vco / ((float_t)(uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_Q3) >> 16) + (float_t)1)) ;
+ PLL3_Clocks->PLL3_R_Frequency = (uint32_t)(float_t)(pll3vco / ((float_t)(uint32_t)((RCC->PLL3DIVR & RCC_PLL3DIVR_R3) >> 24) + (float_t)1)) ;
+ }
+ else
+ {
+ PLL3_Clocks->PLL3_P_Frequency = 0U;
+ PLL3_Clocks->PLL3_Q_Frequency = 0U;
+ PLL3_Clocks->PLL3_R_Frequency = 0U;
+ }
+
+}
+
+/**
+* @brief Returns the PLL1 clock frequencies :PLL1_P_Frequency,PLL1_R_Frequency and PLL1_Q_Frequency
+ * @note The PLL1 clock frequencies 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 The function returns values based on HSE_VALUE, HSI_VALUE or CSI Value multiplied/divided by the PLL factors.
+ * @note This function can be used by the user application to compute the
+ * baud-rate for the communication peripherals or configure other parameters.
+ *
+ * @note Each time PLL1CLK changes, this function must be called to update the
+ * right PLL1CLK value. Otherwise, any configuration based on this function will be incorrect.
+ * @param PLL1_Clocks structure.
+ * @retval None
+ */
+void HAL_RCCEx_GetPLL1ClockFreq(PLL1_ClocksTypeDef *PLL1_Clocks)
+{
+ uint32_t pllsource, pll1m, pll1fracen, hsivalue;
+ float_t fracn1, pll1vco;
+
+ pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC);
+ pll1m = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> 4);
+ pll1fracen = RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN;
+ fracn1 = (float_t)(uint32_t)(pll1fracen * ((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN1) >> 3));
+
+ if (pll1m != 0U)
+ {
+ switch (pllsource)
+ {
+
+ case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
+
+ if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U)
+ {
+ hsivalue = (HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3));
+ pll1vco = ((float_t)hsivalue / (float_t)pll1m) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ }
+ else
+ {
+ pll1vco = ((float_t)HSI_VALUE / (float_t)pll1m) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ }
+ break;
+ case RCC_PLLSOURCE_CSI: /* CSI used as PLL clock source */
+ pll1vco = ((float_t)CSI_VALUE / (float_t)pll1m) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
+ pll1vco = ((float_t)HSE_VALUE / (float_t)pll1m) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ break;
+
+ default:
+ pll1vco = ((float_t)HSI_VALUE / (float_t)pll1m) * ((float_t)(uint32_t)(RCC->PLL1DIVR & RCC_PLL1DIVR_N1) + (fracn1 / (float_t)0x2000) + (float_t)1);
+ break;
+ }
+
+ PLL1_Clocks->PLL1_P_Frequency = (uint32_t)(float_t)(pll1vco / ((float_t)(uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_P1) >> 9) + (float_t)1)) ;
+ PLL1_Clocks->PLL1_Q_Frequency = (uint32_t)(float_t)(pll1vco / ((float_t)(uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_Q1) >> 16) + (float_t)1)) ;
+ PLL1_Clocks->PLL1_R_Frequency = (uint32_t)(float_t)(pll1vco / ((float_t)(uint32_t)((RCC->PLL1DIVR & RCC_PLL1DIVR_R1) >> 24) + (float_t)1)) ;
+ }
+ else
+ {
+ PLL1_Clocks->PLL1_P_Frequency = 0U;
+ PLL1_Clocks->PLL1_Q_Frequency = 0U;
+ PLL1_Clocks->PLL1_R_Frequency = 0U;
+ }
+
+}
+
+/**
+ * @brief Returns the main System frequency
+ * @note Each time System clock changes, this function must be called to update the
+ * right core clock value. Otherwise, any configuration based on this function will be incorrect.
+ * @note The SystemCoreClock CMSIS variable is used to store System current Core Clock Frequency
+ * and updated within this function
+ * @retval HCLK frequency
+ */
+uint32_t HAL_RCCEx_GetD1SysClockFreq(void)
+{
+ uint32_t common_system_clock;
+
+#if defined(RCC_D1CFGR_D1CPRE)
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> (D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE) >> RCC_D1CFGR_D1CPRE_Pos] & 0x1FU);
+#else
+ common_system_clock = HAL_RCC_GetSysClockFreq() >> (D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE) >> RCC_CDCFGR1_CDCPRE_Pos] & 0x1FU);
+#endif
+
+ /* Update the SystemD2Clock global variable */
+#if defined(RCC_D1CFGR_HPRE)
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE) >> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
+#else
+ SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE) >> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
+#endif
+
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ SystemCoreClock = SystemD2Clock;
+#else
+ SystemCoreClock = common_system_clock;
+#endif /* DUAL_CORE && CORE_CM4 */
+
+ return common_system_clock;
+}
+/**
+ * @}
+ */
+
+/** @defgroup RCCEx_Exported_Functions_Group2 Extended System Control functions
+ * @brief Extended Peripheral Control functions
+ * @{
+ */
+/**
+ * @brief Enables the LSE Clock Security System.
+ * @note Prior to enable the LSE Clock Security System, LSE oscillator is to be enabled
+ * with HAL_RCC_OscConfig() and the LSE oscillator clock is to be selected as RTC
+ * clock with HAL_RCCEx_PeriphCLKConfig().
+ * @retval None
+ */
+void HAL_RCCEx_EnableLSECSS(void)
+{
+ SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
+}
+
+/**
+ * @brief Disables the LSE Clock Security System.
+ * @note LSE Clock Security System can only be disabled after a LSE failure detection.
+ * @retval None
+ */
+void HAL_RCCEx_DisableLSECSS(void)
+{
+ CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
+ /* Disable LSE CSS IT if any */
+ __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
+}
+
+/**
+ * @brief Enable the LSE Clock Security System Interrupt & corresponding EXTI line.
+ * @note LSE Clock Security System Interrupt is mapped on EXTI line 18
+ * @retval None
+ */
+void HAL_RCCEx_EnableLSECSS_IT(void)
+{
+ /* Enable LSE CSS */
+ SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
+
+ /* Enable LSE CSS IT */
+ __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
+
+ /* Enable IT on EXTI Line 18 */
+#if defined(DUAL_CORE) && defined(CORE_CM4)
+ __HAL_RCC_C2_LSECSS_EXTI_ENABLE_IT();
+#else
+ __HAL_RCC_LSECSS_EXTI_ENABLE_IT();
+#endif /* DUAL_CORE && CORE_CM4 */
+ __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
+}
+
+/**
+ * @brief Configure the oscillator clock source for wakeup from Stop and CSS backup clock
+ * @param WakeUpClk: Wakeup clock
+ * This parameter can be one of the following values:
+ * @arg RCC_STOP_WAKEUPCLOCK_CSI: CSI oscillator selection
+ * @arg RCC_STOP_WAKEUPCLOCK_HSI: HSI oscillator selection
+ * @note This function shall not be called after the Clock Security System on HSE has been
+ * enabled.
+ * @retval None
+ */
+void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk)
+{
+ assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk));
+
+ __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk);
+}
+
+/**
+ * @brief Configure the oscillator Kernel clock source for wakeup from Stop
+ * @param WakeUpClk: Kernel Wakeup clock
+ * This parameter can be one of the following values:
+ * @arg RCC_STOP_KERWAKEUPCLOCK_CSI: CSI oscillator selection
+ * @arg RCC_STOP_KERWAKEUPCLOCK_HSI: HSI oscillator selection
+ * @retval None
+ */
+void HAL_RCCEx_KerWakeUpStopCLKConfig(uint32_t WakeUpClk)
+{
+ assert_param(IS_RCC_STOP_KERWAKEUPCLOCK(WakeUpClk));
+
+ __HAL_RCC_KERWAKEUPSTOP_CLK_CONFIG(WakeUpClk);
+}
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Enable COREx boot independently of CMx_B option byte value
+ * @param RCC_BootCx: Boot Core to be enabled
+ * This parameter can be one of the following values:
+ * @arg RCC_BOOT_C1: CM7 core selection
+ * @arg RCC_BOOT_C2: CM4 core selection
+ * @note This bit can be set by software but is cleared by hardware after a system reset or STANDBY
+ *
+ * @retval None
+ */
+void HAL_RCCEx_EnableBootCore(uint32_t RCC_BootCx)
+{
+ assert_param(IS_RCC_BOOT_CORE(RCC_BootCx));
+ SET_BIT(RCC->GCR, RCC_BootCx) ;
+}
+
+#endif /*DUAL_CORE*/
+
+#if defined(DUAL_CORE)
+/**
+ * @brief Configure WWDGx to generate a system reset not only CPUx reset(default) when a time-out occurs
+ * @param RCC_WWDGx: WWDGx to be configured
+ * This parameter can be one of the following values:
+ * @arg RCC_WWDG1: WWDG1 generates system reset
+ * @arg RCC_WWDG2: WWDG2 generates system reset
+ * @note This bit can be set by software but is cleared by hardware during a system reset
+ *
+ * @retval None
+ */
+void HAL_RCCEx_WWDGxSysResetConfig(uint32_t RCC_WWDGx)
+{
+ assert_param(IS_RCC_SCOPE_WWDG(RCC_WWDGx));
+ SET_BIT(RCC->GCR, RCC_WWDGx) ;
+}
+
+#else
+#if defined(RCC_GCR_WW1RSC)
+/**
+ * @brief Configure WWDG1 to generate a system reset not only CPU reset(default) when a time-out occurs
+ * @param RCC_WWDGx: WWDGx to be configured
+ * This parameter can be one of the following values:
+ * @arg RCC_WWDG1: WWDG1 generates system reset
+ * @note This bit can be set by software but is cleared by hardware during a system reset
+ *
+ * @retval None
+ */
+void HAL_RCCEx_WWDGxSysResetConfig(uint32_t RCC_WWDGx)
+{
+ assert_param(IS_RCC_SCOPE_WWDG(RCC_WWDGx));
+ SET_BIT(RCC->GCR, RCC_WWDGx) ;
+}
+#endif
+#endif /*DUAL_CORE*/
+
+/**
+ * @}
+ */
+
+/** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions
+ * @brief Extended Clock Recovery System Control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended Clock Recovery System Control functions #####
+ ===============================================================================
+ [..]
+ For devices with Clock Recovery System feature (CRS), RCC Extension HAL driver can be used as follows:
+
+ (#) In System clock config, HSI48 needs to be enabled
+
+ (#) Enable CRS clock in IP MSP init which will use CRS functions
+
+ (#) Call CRS functions as follows:
+ (##) Prepare synchronization configuration necessary for HSI48 calibration
+ (+++) Default values can be set for frequency Error Measurement (reload and error limit)
+ and also HSI48 oscillator smooth trimming.
+ (+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate
+ directly reload value with target and synchronization frequencies values
+ (##) Call function HAL_RCCEx_CRSConfig which
+ (+++) Resets CRS registers to their default values.
+ (+++) Configures CRS registers with synchronization configuration
+ (+++) Enables automatic calibration and frequency error counter feature
+ Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the
+ periodic USB SOF will not be generated by the host. No SYNC signal will therefore be
+ provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock
+ precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs
+ should be used as SYNC signal.
+
+ (##) A polling function is provided to wait for complete synchronization
+ (+++) Call function HAL_RCCEx_CRSWaitSynchronization()
+ (+++) According to CRS status, user can decide to adjust again the calibration or continue
+ application if synchronization is OK
+
+ (#) User can retrieve information related to synchronization in calling function
+ HAL_RCCEx_CRSGetSynchronizationInfo()
+
+ (#) Regarding synchronization status and synchronization information, user can try a new calibration
+ in changing synchronization configuration and call again HAL_RCCEx_CRSConfig.
+ Note: When the SYNC event is detected during the down-counting phase (before reaching the zero value),
+ it means that the actual frequency is lower than the target (and so, that the TRIM value should be
+ incremented), while when it is detected during the up-counting phase it means that the actual frequency
+ is higher (and that the TRIM value should be decremented).
+
+ (#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go
+ through CRS Handler (CRS_IRQn/CRS_IRQHandler)
+ (++) Call function HAL_RCCEx_CRSConfig()
+ (++) Enable CRS_IRQn (thanks to NVIC functions)
+ (++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT)
+ (++) Implement CRS status management in the following user callbacks called from
+ HAL_RCCEx_CRS_IRQHandler():
+ (+++) HAL_RCCEx_CRS_SyncOkCallback()
+ (+++) HAL_RCCEx_CRS_SyncWarnCallback()
+ (+++) HAL_RCCEx_CRS_ExpectedSyncCallback()
+ (+++) HAL_RCCEx_CRS_ErrorCallback()
+
+ (#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate().
+ This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler)
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Start automatic synchronization for polling mode
+ * @param pInit Pointer on RCC_CRSInitTypeDef structure
+ * @retval None
+ */
+void HAL_RCCEx_CRSConfig(const RCC_CRSInitTypeDef *pInit)
+{
+ uint32_t value;
+
+ /* Check the parameters */
+ assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler));
+ assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source));
+ assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity));
+ assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue));
+ assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue));
+ assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue));
+
+ /* CONFIGURATION */
+
+ /* Before configuration, reset CRS registers to their default values*/
+ __HAL_RCC_CRS_FORCE_RESET();
+ __HAL_RCC_CRS_RELEASE_RESET();
+
+ /* Set the SYNCDIV[2:0] bits according to Pre-scaler value */
+ /* Set the SYNCSRC[1:0] bits according to Source value */
+ /* Set the SYNCSPOL bit according to Polarity value */
+ if ((HAL_GetREVID() <= REV_ID_Y) && (pInit->Source == RCC_CRS_SYNC_SOURCE_USB2))
+ {
+ /* Use Rev.Y value of USB2 */
+ value = (pInit->Prescaler | RCC_CRS_SYNC_SOURCE_PIN | pInit->Polarity);
+ }
+ else
+ {
+ value = (pInit->Prescaler | pInit->Source | pInit->Polarity);
+ }
+ /* Set the RELOAD[15:0] bits according to ReloadValue value */
+ value |= pInit->ReloadValue;
+ /* Set the FELIM[7:0] bits according to ErrorLimitValue value */
+ value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_Pos);
+ WRITE_REG(CRS->CFGR, value);
+
+ /* Adjust HSI48 oscillator smooth trimming */
+ /* Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value */
+ MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos));
+
+ /* START AUTOMATIC SYNCHRONIZATION*/
+
+ /* Enable Automatic trimming & Frequency error counter */
+ SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN);
+}
+
+/**
+ * @brief Generate the software synchronization event
+ * @retval None
+ */
+void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)
+{
+ SET_BIT(CRS->CR, CRS_CR_SWSYNC);
+}
+
+/**
+ * @brief Return synchronization info
+ * @param pSynchroInfo Pointer on RCC_CRSSynchroInfoTypeDef structure
+ * @retval None
+ */
+void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo)
+{
+ /* Check the parameter */
+ assert_param(pSynchroInfo != (void *)NULL);
+
+ /* Get the reload value */
+ pSynchroInfo->ReloadValue = (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD));
+
+ /* Get HSI48 oscillator smooth trimming */
+ pSynchroInfo->HSI48CalibrationValue = (uint32_t)(READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos);
+
+ /* Get Frequency error capture */
+ pSynchroInfo->FreqErrorCapture = (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos);
+
+ /* Get Frequency error direction */
+ pSynchroInfo->FreqErrorDirection = (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FEDIR));
+}
+
+/**
+* @brief Wait for CRS Synchronization status.
+* @param Timeout Duration of the time-out
+* @note Timeout is based on the maximum time to receive a SYNC event based on synchronization
+* frequency.
+* @note If Time-out set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned.
+* @retval Combination of Synchronization status
+* This parameter can be a combination of the following values:
+* @arg @ref RCC_CRS_TIMEOUT
+* @arg @ref RCC_CRS_SYNCOK
+* @arg @ref RCC_CRS_SYNCWARN
+* @arg @ref RCC_CRS_SYNCERR
+* @arg @ref RCC_CRS_SYNCMISS
+* @arg @ref RCC_CRS_TRIMOVF
+*/
+uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)
+{
+ uint32_t crsstatus = RCC_CRS_NONE;
+ uint32_t tickstart;
+
+ /* Get time-out */
+ tickstart = HAL_GetTick();
+
+ /* Wait for CRS flag or time-out detection */
+ do
+ {
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ crsstatus = RCC_CRS_TIMEOUT;
+ }
+ }
+ /* Check CRS SYNCOK flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK))
+ {
+ /* CRS SYNC event OK */
+ crsstatus |= RCC_CRS_SYNCOK;
+
+ /* Clear CRS SYNC event OK bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK);
+ }
+
+ /* Check CRS SYNCWARN flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN))
+ {
+ /* CRS SYNC warning */
+ crsstatus |= RCC_CRS_SYNCWARN;
+
+ /* Clear CRS SYNCWARN bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN);
+ }
+
+ /* Check CRS TRIM overflow flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF))
+ {
+ /* CRS SYNC Error */
+ crsstatus |= RCC_CRS_TRIMOVF;
+
+ /* Clear CRS Error bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF);
+ }
+
+ /* Check CRS Error flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR))
+ {
+ /* CRS SYNC Error */
+ crsstatus |= RCC_CRS_SYNCERR;
+
+ /* Clear CRS Error bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR);
+ }
+
+ /* Check CRS SYNC Missed flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS))
+ {
+ /* CRS SYNC Missed */
+ crsstatus |= RCC_CRS_SYNCMISS;
+
+ /* Clear CRS SYNC Missed bit */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS);
+ }
+
+ /* Check CRS Expected SYNC flag */
+ if (__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC))
+ {
+ /* frequency error counter reached a zero value */
+ __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC);
+ }
+ }
+ while (RCC_CRS_NONE == crsstatus);
+
+ return crsstatus;
+}
+
+/**
+ * @brief Handle the Clock Recovery System interrupt request.
+ * @retval None
+ */
+void HAL_RCCEx_CRS_IRQHandler(void)
+{
+ uint32_t crserror = RCC_CRS_NONE;
+ /* Get current IT flags and IT sources values */
+ uint32_t itflags = READ_REG(CRS->ISR);
+ uint32_t itsources = READ_REG(CRS->CR);
+
+ /* Check CRS SYNCOK flag */
+ if (((itflags & RCC_CRS_FLAG_SYNCOK) != 0U) && ((itsources & RCC_CRS_IT_SYNCOK) != 0U))
+ {
+ /* Clear CRS SYNC event OK flag */
+ WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC);
+
+ /* user callback */
+ HAL_RCCEx_CRS_SyncOkCallback();
+ }
+ /* Check CRS SYNCWARN flag */
+ else if (((itflags & RCC_CRS_FLAG_SYNCWARN) != 0U) && ((itsources & RCC_CRS_IT_SYNCWARN) != 0U))
+ {
+ /* Clear CRS SYNCWARN flag */
+ WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC);
+
+ /* user callback */
+ HAL_RCCEx_CRS_SyncWarnCallback();
+ }
+ /* Check CRS Expected SYNC flag */
+ else if (((itflags & RCC_CRS_FLAG_ESYNC) != 0U) && ((itsources & RCC_CRS_IT_ESYNC) != 0U))
+ {
+ /* frequency error counter reached a zero value */
+ WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC);
+
+ /* user callback */
+ HAL_RCCEx_CRS_ExpectedSyncCallback();
+ }
+ /* Check CRS Error flags */
+ else
+ {
+ if (((itflags & RCC_CRS_FLAG_ERR) != 0U) && ((itsources & RCC_CRS_IT_ERR) != 0U))
+ {
+ if ((itflags & RCC_CRS_FLAG_SYNCERR) != 0U)
+ {
+ crserror |= RCC_CRS_SYNCERR;
+ }
+ if ((itflags & RCC_CRS_FLAG_SYNCMISS) != 0U)
+ {
+ crserror |= RCC_CRS_SYNCMISS;
+ }
+ if ((itflags & RCC_CRS_FLAG_TRIMOVF) != 0U)
+ {
+ crserror |= RCC_CRS_TRIMOVF;
+ }
+
+ /* Clear CRS Error flags */
+ WRITE_REG(CRS->ICR, CRS_ICR_ERRC);
+
+ /* user error callback */
+ HAL_RCCEx_CRS_ErrorCallback(crserror);
+ }
+ }
+}
+
+/**
+ * @brief RCCEx Clock Recovery System SYNCOK interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_SyncOkCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief RCCEx Clock Recovery System SYNCWARN interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_SyncWarnCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief RCCEx Clock Recovery System Expected SYNC interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file
+ */
+}
+
+/**
+ * @brief RCCEx Clock Recovery System Error interrupt callback.
+ * @param Error Combination of Error status.
+ * This parameter can be a combination of the following values:
+ * @arg @ref RCC_CRS_SYNCERR
+ * @arg @ref RCC_CRS_SYNCMISS
+ * @arg @ref RCC_CRS_TRIMOVF
+ * @retval none
+ */
+__weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Error);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file
+ */
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup RCCEx_Private_functions RCCEx Private Functions
+ * @{
+ */
+/**
+ * @brief Configure the PLL2 VCI,VCO ranges, multiplication and division factors and enable it
+ * @param pll2: Pointer to an RCC_PLL2InitTypeDef structure that
+ * contains the configuration parameters as well as VCI, VCO clock ranges.
+ * @param Divider divider parameter to be updated
+ * @note PLL2 is temporary disabled to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLL2_Config(const RCC_PLL2InitTypeDef *pll2, uint32_t Divider)
+{
+
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+ assert_param(IS_RCC_PLL2M_VALUE(pll2->PLL2M));
+ assert_param(IS_RCC_PLL2N_VALUE(pll2->PLL2N));
+ assert_param(IS_RCC_PLL2P_VALUE(pll2->PLL2P));
+ assert_param(IS_RCC_PLL2R_VALUE(pll2->PLL2R));
+ assert_param(IS_RCC_PLL2Q_VALUE(pll2->PLL2Q));
+ assert_param(IS_RCC_PLL2RGE_VALUE(pll2->PLL2RGE));
+ assert_param(IS_RCC_PLL2VCO_VALUE(pll2->PLL2VCOSEL));
+ assert_param(IS_RCC_PLLFRACN_VALUE(pll2->PLL2FRACN));
+
+ /* Check that PLL2 OSC clock source is already set */
+ if (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_NONE)
+ {
+ return HAL_ERROR;
+ }
+
+
+ else
+ {
+ /* Disable PLL2. */
+ __HAL_RCC_PLL2_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL is disabled */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure PLL2 multiplication and division factors. */
+ __HAL_RCC_PLL2_CONFIG(pll2->PLL2M,
+ pll2->PLL2N,
+ pll2->PLL2P,
+ pll2->PLL2Q,
+ pll2->PLL2R);
+
+ /* Select PLL2 input reference frequency range: VCI */
+ __HAL_RCC_PLL2_VCIRANGE(pll2->PLL2RGE) ;
+
+ /* Select PLL2 output frequency range : VCO */
+ __HAL_RCC_PLL2_VCORANGE(pll2->PLL2VCOSEL) ;
+
+ /* Disable PLL2FRACN . */
+ __HAL_RCC_PLL2FRACN_DISABLE();
+
+ /* Configures PLL2 clock Fractional Part Of The Multiplication Factor */
+ __HAL_RCC_PLL2FRACN_CONFIG(pll2->PLL2FRACN);
+
+ /* Enable PLL2FRACN . */
+ __HAL_RCC_PLL2FRACN_ENABLE();
+
+ /* Enable the PLL2 clock output */
+ if (Divider == DIVIDER_P_UPDATE)
+ {
+ __HAL_RCC_PLL2CLKOUT_ENABLE(RCC_PLL2_DIVP);
+ }
+ else if (Divider == DIVIDER_Q_UPDATE)
+ {
+ __HAL_RCC_PLL2CLKOUT_ENABLE(RCC_PLL2_DIVQ);
+ }
+ else
+ {
+ __HAL_RCC_PLL2CLKOUT_ENABLE(RCC_PLL2_DIVR);
+ }
+
+ /* Enable PLL2. */
+ __HAL_RCC_PLL2_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL2 is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ }
+
+
+ return status;
+}
+
+
+/**
+ * @brief Configure the PLL3 VCI,VCO ranges, multiplication and division factors and enable it
+ * @param pll3: Pointer to an RCC_PLL3InitTypeDef structure that
+ * contains the configuration parameters as well as VCI, VCO clock ranges.
+ * @param Divider divider parameter to be updated
+ * @note PLL3 is temporary disabled to apply new parameters
+ *
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef RCCEx_PLL3_Config(const RCC_PLL3InitTypeDef *pll3, uint32_t Divider)
+{
+ uint32_t tickstart;
+ HAL_StatusTypeDef status = HAL_OK;
+ assert_param(IS_RCC_PLL3M_VALUE(pll3->PLL3M));
+ assert_param(IS_RCC_PLL3N_VALUE(pll3->PLL3N));
+ assert_param(IS_RCC_PLL3P_VALUE(pll3->PLL3P));
+ assert_param(IS_RCC_PLL3R_VALUE(pll3->PLL3R));
+ assert_param(IS_RCC_PLL3Q_VALUE(pll3->PLL3Q));
+ assert_param(IS_RCC_PLL3RGE_VALUE(pll3->PLL3RGE));
+ assert_param(IS_RCC_PLL3VCO_VALUE(pll3->PLL3VCOSEL));
+ assert_param(IS_RCC_PLLFRACN_VALUE(pll3->PLL3FRACN));
+
+ /* Check that PLL3 OSC clock source is already set */
+ if (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_NONE)
+ {
+ return HAL_ERROR;
+ }
+
+
+ else
+ {
+ /* Disable PLL3. */
+ __HAL_RCC_PLL3_DISABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+ /* Wait till PLL3 is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY) != 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL3_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Configure the PLL3 multiplication and division factors. */
+ __HAL_RCC_PLL3_CONFIG(pll3->PLL3M,
+ pll3->PLL3N,
+ pll3->PLL3P,
+ pll3->PLL3Q,
+ pll3->PLL3R);
+
+ /* Select PLL3 input reference frequency range: VCI */
+ __HAL_RCC_PLL3_VCIRANGE(pll3->PLL3RGE) ;
+
+ /* Select PLL3 output frequency range : VCO */
+ __HAL_RCC_PLL3_VCORANGE(pll3->PLL3VCOSEL) ;
+
+ /* Disable PLL3FRACN . */
+ __HAL_RCC_PLL3FRACN_DISABLE();
+
+ /* Configures PLL3 clock Fractional Part Of The Multiplication Factor */
+ __HAL_RCC_PLL3FRACN_CONFIG(pll3->PLL3FRACN);
+
+ /* Enable PLL3FRACN . */
+ __HAL_RCC_PLL3FRACN_ENABLE();
+
+ /* Enable the PLL3 clock output */
+ if (Divider == DIVIDER_P_UPDATE)
+ {
+ __HAL_RCC_PLL3CLKOUT_ENABLE(RCC_PLL3_DIVP);
+ }
+ else if (Divider == DIVIDER_Q_UPDATE)
+ {
+ __HAL_RCC_PLL3CLKOUT_ENABLE(RCC_PLL3_DIVQ);
+ }
+ else
+ {
+ __HAL_RCC_PLL3CLKOUT_ENABLE(RCC_PLL3_DIVR);
+ }
+
+ /* Enable PLL3. */
+ __HAL_RCC_PLL3_ENABLE();
+
+ /* Get Start Tick*/
+ tickstart = HAL_GetTick();
+
+ /* Wait till PLL3 is ready */
+ while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY) == 0U)
+ {
+ if ((HAL_GetTick() - tickstart) > PLL3_TIMEOUT_VALUE)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+
+ }
+
+
+ return status;
+}
+
+/**
+ * @brief Handle the RCC LSE Clock Security System interrupt request.
+ * @retval None
+ */
+void HAL_RCCEx_LSECSS_IRQHandler(void)
+{
+ /* Check RCC LSE CSSF flag */
+ if (__HAL_RCC_GET_IT(RCC_IT_LSECSS))
+ {
+
+ /* Clear RCC LSE CSS pending bit */
+ __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
+
+ /* RCC LSE Clock Security System interrupt user callback */
+ HAL_RCCEx_LSECSS_Callback();
+
+ }
+}
+
+/**
+ * @brief RCCEx LSE Clock Security System interrupt callback.
+ * @retval none
+ */
+__weak void HAL_RCCEx_LSECSS_Callback(void)
+{
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file
+ */
+}
+
+
+
+/**
+ * @}
+ */
+
+#endif /* HAL_RCC_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai.c
new file mode 100755
index 0000000..6a11433
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai.c
@@ -0,0 +1,2946 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_sai.c
+ * @author MCD Application Team
+ * @brief SAI HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Serial Audio Interface (SAI) peripheral:
+ * + Initialization/de-initialization functions
+ * + I/O operation functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+
+ [..]
+ The SAI HAL driver can be used as follows:
+
+ (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai).
+ (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API:
+ (##) Enable the SAI interface clock.
+ (##) SAI pins configuration:
+ (+++) Enable the clock for the SAI GPIOs.
+ (+++) Configure these SAI pins as alternate function pull-up.
+ (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT()
+ and HAL_SAI_Receive_IT() APIs):
+ (+++) Configure the SAI interrupt priority.
+ (+++) Enable the NVIC SAI IRQ handle.
+
+ (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA()
+ and HAL_SAI_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 SAI DMA Tx/Rx handle.
+ (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
+ DMA Tx/Rx Stream.
+
+ (#) The initialization can be done by two ways
+ (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init().
+ (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol().
+
+ [..]
+ (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt)
+ will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT()
+ inside the transmit and receive process.
+ [..]
+ (@) Make sure that either:
+ (+@) PLLSAI1CLK output is configured or
+ (+@) PLLSAI2CLK output is configured or
+ (+@) PLLSAI3CLK output is configured or
+ (+@) PLLSAI4ACLK output is configured or
+ (+@) PLLSAI4BCLK output is configured or
+ (+@) External clock source is configured after setting correctly
+ the define constant EXTERNAL_CLOCK_VALUE in the stm32h7xx_hal_conf.h file.
+
+ [..]
+ (@) In master Tx mode: enabling the audio block immediately generates the bit clock
+ for the external slaves even if there is no data in the FIFO, However FS signal
+ generation is conditioned by the presence of data in the FIFO.
+
+ [..]
+ (@) In master Rx mode: enabling the audio block immediately generates the bit clock
+ and FS signal for the external slaves.
+
+ [..]
+ (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior:
+ (+@) First bit Offset <= (SLOT size - Data size)
+ (+@) Data size <= SLOT size
+ (+@) Number of SLOT x SLOT size = Frame length
+ (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected.
+
+ [..]
+ (@) PDM interface can be activated through HAL_SAI_Init function.
+ Please note that PDM interface is only available for SAI1 or SAI4 sub-block A.
+ PDM microphone delays can be tuned with HAL_SAIEx_ConfigPdmMicDelay function.
+
+ [..]
+ Three operation modes are available within this driver :
+
+ *** Polling mode IO operation ***
+ =================================
+ [..]
+ (+) Send an amount of data in blocking mode using HAL_SAI_Transmit()
+ (+) Receive an amount of data in blocking mode using HAL_SAI_Receive()
+
+ *** Interrupt mode IO operation ***
+ ===================================
+ [..]
+ (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT()
+ (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT()
+ (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
+ (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SAI_ErrorCallback()
+
+ *** DMA mode IO operation ***
+ =============================
+ [..]
+ (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA()
+ (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SAI_TxCpltCallback()
+ (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA()
+ (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can
+ add his own code by customization of function pointer HAL_SAI_RxCpltCallback()
+ (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can
+ add his own code by customization of function pointer HAL_SAI_ErrorCallback()
+ (+) Pause the DMA Transfer using HAL_SAI_DMAPause()
+ (+) Resume the DMA Transfer using HAL_SAI_DMAResume()
+ (+) Stop the DMA Transfer using HAL_SAI_DMAStop()
+
+ *** SAI HAL driver additional function list ***
+ ===============================================
+ [..]
+ Below the list the others API available SAI HAL driver :
+
+ (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode
+ (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode
+ (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode
+ (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode
+ (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo.
+ (+) HAL_SAI_Abort(): Abort the current transfer
+
+ *** SAI HAL driver macros list ***
+ ==================================
+ [..]
+ Below the list of most used macros in SAI HAL driver :
+
+ (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral
+ (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral
+ (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts
+ (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts
+ (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is
+ enabled or disabled
+ (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not
+
+ *** Callback registration ***
+ =============================
+ [..]
+ The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+ Use functions HAL_SAI_RegisterCallback() to register a user callback.
+
+ [..]
+ Function HAL_SAI_RegisterCallback() allows to register following callbacks:
+ (+) RxCpltCallback : SAI receive complete.
+ (+) RxHalfCpltCallback : SAI receive half complete.
+ (+) TxCpltCallback : SAI transmit complete.
+ (+) TxHalfCpltCallback : SAI transmit half complete.
+ (+) ErrorCallback : SAI error.
+ (+) MspInitCallback : SAI MspInit.
+ (+) MspDeInitCallback : SAI MspDeInit.
+ [..]
+ This function takes as parameters the HAL peripheral handle, the callback ID
+ and a pointer to the user callback function.
+
+ [..]
+ Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
+ and the callback ID.
+ [..]
+ This function allows to reset following callbacks:
+ (+) RxCpltCallback : SAI receive complete.
+ (+) RxHalfCpltCallback : SAI receive half complete.
+ (+) TxCpltCallback : SAI transmit complete.
+ (+) TxHalfCpltCallback : SAI transmit half complete.
+ (+) ErrorCallback : SAI error.
+ (+) MspInitCallback : SAI MspInit.
+ (+) MspDeInitCallback : SAI MspDeInit.
+
+ [..]
+ By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak functions:
+ examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback().
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak functions in the HAL_SAI_Init
+ and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
+
+ [..]
+ Callbacks can be registered/unregistered in READY state only.
+ Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
+ in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
+ during the Init/DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_SAI_RegisterCallback before calling HAL_SAI_DeInit
+ or HAL_SAI_Init function.
+
+ [..]
+ When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak callbacks are used.
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup SAI SAI
+ * @brief SAI HAL module driver
+ * @{
+ */
+
+#ifdef HAL_SAI_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/** @defgroup SAI_Private_Typedefs SAI Private Typedefs
+ * @{
+ */
+typedef enum
+{
+ SAI_MODE_DMA,
+ SAI_MODE_IT
+} SAI_ModeTypedef;
+/**
+ * @}
+ */
+
+/* Private define ------------------------------------------------------------*/
+/** @defgroup SAI_Private_Constants SAI Private Constants
+ * @{
+ */
+#define SAI_DEFAULT_TIMEOUT 4U
+#define SAI_LONG_TIMEOUT 1000U
+#define SAI_SPDIF_FRAME_LENGTH 64U
+#define SAI_AC97_FRAME_LENGTH 256U
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @defgroup SAI_Private_Functions SAI Private Functions
+ * @{
+ */
+static void SAI_FillFifo(SAI_HandleTypeDef *hsai);
+static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode);
+static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
+static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot);
+
+static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai);
+static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai);
+static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai);
+static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai);
+static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai);
+static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai);
+static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai);
+
+static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma);
+static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
+static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma);
+static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
+static void SAI_DMAError(DMA_HandleTypeDef *hdma);
+static void SAI_DMAAbort(DMA_HandleTypeDef *hdma);
+/**
+ * @}
+ */
+
+/* Exported functions ---------------------------------------------------------*/
+/** @defgroup SAI_Exported_Functions SAI Exported Functions
+ * @{
+ */
+
+/** @defgroup SAI_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 SAIx peripheral:
+
+ (+) User must implement HAL_SAI_MspInit() function in which he configures
+ all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
+
+ (+) Call the function HAL_SAI_Init() to configure the selected device with
+ the selected configuration:
+ (++) Mode (Master/slave TX/RX)
+ (++) Protocol
+ (++) Data Size
+ (++) MCLK Output
+ (++) Audio frequency
+ (++) FIFO Threshold
+ (++) Frame Config
+ (++) Slot Config
+ (++) PDM Config
+
+ (+) Call the function HAL_SAI_DeInit() to restore the default configuration
+ of the selected SAI peripheral.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the structure FrameInit, SlotInit and the low part of
+ * Init according to the specified parameters and call the function
+ * HAL_SAI_Init to initialize the SAI block.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param protocol one of the supported protocol @ref SAI_Protocol
+ * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
+ * the configuration information for SAI module.
+ * @param nbslot Number of slot.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the parameters */
+ assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol));
+ assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize));
+
+ switch (protocol)
+ {
+ case SAI_I2S_STANDARD :
+ case SAI_I2S_MSBJUSTIFIED :
+ case SAI_I2S_LSBJUSTIFIED :
+ status = SAI_InitI2S(hsai, protocol, datasize, nbslot);
+ break;
+ case SAI_PCM_LONG :
+ case SAI_PCM_SHORT :
+ status = SAI_InitPCM(hsai, protocol, datasize, nbslot);
+ break;
+ default :
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ status = HAL_SAI_Init(hsai);
+ }
+
+ return status;
+}
+
+/**
+ * @brief Initialize the SAI according to the specified parameters.
+ * in the SAI_InitTypeDef structure and initialize the associated handle.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai)
+{
+ uint32_t tmpregisterGCR;
+ uint32_t ckstr_bits;
+ uint32_t syncen_bits;
+ SAI_TypeDef *SaiBaseAddress;
+
+ /* Check the SAI handle allocation */
+ if (hsai == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* check the instance */
+ assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance));
+
+ /* Check the SAI Block parameters */
+ assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency));
+ assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol));
+ assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode));
+ assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize));
+ assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit));
+ assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing));
+ assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro));
+#if defined(SAI_VER_V2_X)
+ /* SAI Peripheral version depends on STM32H7 device revision ID */
+ if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
+ {
+ assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
+ }
+#else /* SAI_VER_V2_1 */
+ assert_param(IS_SAI_BLOCK_MCK_OUTPUT(hsai->Init.MckOutput));
+#endif /* SAI_VER_V2_X */
+ assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive));
+ assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider));
+ assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold));
+ assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode));
+ assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode));
+ assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState));
+ assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt));
+ assert_param(IS_SAI_BLOCK_MCK_OVERSAMPLING(hsai->Init.MckOverSampling));
+
+ /* Check the SAI Block Frame parameters */
+ assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength));
+ assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength));
+ assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition));
+ assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity));
+ assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset));
+
+ /* Check the SAI Block Slot parameters */
+ assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset));
+ assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize));
+ assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber));
+ assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive));
+
+ /* Check the SAI PDM parameters */
+ assert_param(IS_FUNCTIONAL_STATE(hsai->Init.PdmInit.Activation));
+ if (hsai->Init.PdmInit.Activation == ENABLE)
+ {
+ assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(hsai->Init.PdmInit.MicPairsNbr));
+ assert_param(IS_SAI_PDM_CLOCK_ENABLE(hsai->Init.PdmInit.ClockEnable));
+ /* Check that SAI sub-block is SAI1 or SAI4 sub-block A, in master RX mode with free protocol */
+#if defined(SAI4)
+ if (((hsai->Instance != SAI1_Block_A) && (hsai->Instance != SAI4_Block_A)) ||
+ (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
+ (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
+ {
+ return HAL_ERROR;
+ }
+#else
+ if ((hsai->Instance != SAI1_Block_A) ||
+ (hsai->Init.AudioMode != SAI_MODEMASTER_RX) ||
+ (hsai->Init.Protocol != SAI_FREE_PROTOCOL))
+ {
+ return HAL_ERROR;
+ }
+#endif /* SAI4 */
+ }
+
+ /* Get the SAI base address according to the SAI handle */
+ if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
+ {
+ SaiBaseAddress = SAI1;
+ }
+#if defined(SAI2)
+ else if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
+ {
+ SaiBaseAddress = SAI2;
+ }
+#endif /* SAI2 */
+#if defined(SAI3)
+ else if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
+ {
+ SaiBaseAddress = SAI3;
+ }
+#endif /* SAI3 */
+#if defined(SAI4)
+ else if ((hsai->Instance == SAI4_Block_A) || (hsai->Instance == SAI4_Block_B))
+ {
+ SaiBaseAddress = SAI4;
+ }
+#endif /* SAI4 */
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hsai->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ /* Reset callback pointers to the weak predefined callbacks */
+ hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
+ hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
+ hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
+ hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
+ hsai->ErrorCallback = HAL_SAI_ErrorCallback;
+
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ if (hsai->MspInitCallback == NULL)
+ {
+ hsai->MspInitCallback = HAL_SAI_MspInit;
+ }
+ hsai->MspInitCallback(hsai);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_SAI_MspInit(hsai);
+#endif
+ }
+
+ /* Disable the selected SAI peripheral */
+ if(SAI_Disable(hsai) != HAL_OK)
+ {
+ return HAL_ERROR;
+ }
+
+ hsai->State = HAL_SAI_STATE_BUSY;
+
+ /* SAI Block Synchro Configuration -----------------------------------------*/
+ /* This setting must be done with both audio block (A & B) disabled */
+ switch (hsai->Init.SynchroExt)
+ {
+ case SAI_SYNCEXT_DISABLE :
+ tmpregisterGCR = 0;
+ break;
+ case SAI_SYNCEXT_OUTBLOCKA_ENABLE :
+ tmpregisterGCR = SAI_GCR_SYNCOUT_0;
+ break;
+ case SAI_SYNCEXT_OUTBLOCKB_ENABLE :
+ tmpregisterGCR = SAI_GCR_SYNCOUT_1;
+ break;
+ default:
+ tmpregisterGCR = 0;
+ break;
+ }
+
+ switch (hsai->Init.Synchro)
+ {
+ case SAI_ASYNCHRONOUS :
+ syncen_bits = 0;
+ break;
+ case SAI_SYNCHRONOUS :
+ syncen_bits = SAI_xCR1_SYNCEN_0;
+ break;
+ case SAI_SYNCHRONOUS_EXT_SAI1 :
+ syncen_bits = SAI_xCR1_SYNCEN_1;
+ break;
+#if defined(SAI2)
+ case SAI_SYNCHRONOUS_EXT_SAI2 :
+ syncen_bits = SAI_xCR1_SYNCEN_1;
+ tmpregisterGCR |= SAI_GCR_SYNCIN_0;
+ break;
+#endif /* SAI2 */
+#if defined(SAI3)
+ case SAI_SYNCHRONOUS_EXT_SAI3 :
+ syncen_bits = SAI_xCR1_SYNCEN_1;
+ tmpregisterGCR |= SAI_GCR_SYNCIN_1;
+ break;
+#endif /* SAI3 */
+#if defined(SAI4)
+ case SAI_SYNCHRONOUS_EXT_SAI4 :
+ syncen_bits = SAI_xCR1_SYNCEN_1;
+ tmpregisterGCR |= (SAI_GCR_SYNCIN_1 | SAI_GCR_SYNCIN_0);
+ break;
+#endif /* SAI4 */
+ default:
+ syncen_bits = 0;
+ break;
+ }
+
+ /* Set the SAI Block Synchro Configuration */
+ SaiBaseAddress->GCR = tmpregisterGCR;
+
+ if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV)
+ {
+ uint32_t freq = 0;
+ uint32_t tmpval;
+
+ /* In this case, the MCKDIV value is calculated to get AudioFrequency */
+ if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B))
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1);
+ }
+
+#if defined(SAI2)
+#if defined(RCC_PERIPHCLK_SAI2)
+ if ((hsai->Instance == SAI2_Block_A) || (hsai->Instance == SAI2_Block_B))
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2);
+ }
+#else
+ if (hsai->Instance == SAI2_Block_A)
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2A);
+ }
+ if (hsai->Instance == SAI2_Block_B)
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2B);
+ }
+#endif /* RCC_PERIPHCLK_SAI2 */
+#endif /* SAI2 */
+
+#if defined(SAI3)
+ if ((hsai->Instance == SAI3_Block_A) || (hsai->Instance == SAI3_Block_B))
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI3);
+ }
+#endif /* SAI3 */
+#if defined(SAI4)
+ if (hsai->Instance == SAI4_Block_A)
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4A);
+ }
+ if (hsai->Instance == SAI4_Block_B)
+ {
+ freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI4B);
+ }
+#endif /* SAI4 */
+
+ /* Configure Master Clock Divider using the following formula :
+ - If NODIV = 1 :
+ MCKDIV[5:0] = SAI_CK_x / (FS * (FRL + 1))
+ - If NODIV = 0 :
+ MCKDIV[5:0] = SAI_CK_x / (FS * (OSR + 1) * 256) */
+ if (hsai->Init.NoDivider == SAI_MASTERDIVIDER_DISABLE)
+ {
+ /* NODIV = 1 */
+ uint32_t tmpframelength;
+
+ if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
+ {
+ /* For SPDIF protocol, frame length is set by hardware to 64 */
+ tmpframelength = SAI_SPDIF_FRAME_LENGTH;
+ }
+ else if (hsai->Init.Protocol == SAI_AC97_PROTOCOL)
+ {
+ /* For AC97 protocol, frame length is set by hardware to 256 */
+ tmpframelength = SAI_AC97_FRAME_LENGTH;
+ }
+ else
+ {
+ /* For free protocol, frame length is set by user */
+ tmpframelength = hsai->FrameInit.FrameLength;
+ }
+
+ /* (freq x 10) to keep Significant digits */
+ tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmpframelength);
+ }
+ else
+ {
+ /* NODIV = 0 */
+ uint32_t tmposr;
+ tmposr = (hsai->Init.MckOverSampling == SAI_MCK_OVERSAMPLING_ENABLE) ? 2U : 1U;
+ /* (freq x 10) to keep Significant digits */
+ tmpval = (freq * 10U) / (hsai->Init.AudioFrequency * tmposr * 256U);
+ }
+ hsai->Init.Mckdiv = tmpval / 10U;
+
+ /* Round result to the nearest integer */
+ if ((tmpval % 10U) > 8U)
+ {
+ hsai->Init.Mckdiv += 1U;
+ }
+
+ /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */
+ if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL)
+ {
+ hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1;
+ }
+ }
+
+ /* Check the SAI Block master clock divider parameter */
+ assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv));
+
+ /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
+ if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
+ {
+ /* Transmit */
+ ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
+ }
+ else
+ {
+ /* Receive */
+ ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
+ }
+
+ /* SAI Block Configuration -------------------------------------------------*/
+ /* SAI CR1 Configuration */
+#if defined(SAI_VER_V2_X) /* SAI Peripheral version depends on STM32H7 device revision ID */
+
+ if (HAL_GetREVID() >= REV_ID_B) /* STM32H7xx Rev.B and above */
+ {
+ hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
+ SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
+ SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
+ SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
+ SAI_xCR1_MCKEN);
+
+ hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
+ hsai->Init.DataSize | hsai->Init.FirstBit | \
+ ckstr_bits | syncen_bits | \
+ hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
+ hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
+ hsai->Init.MckOverSampling | hsai->Init.MckOutput);
+ }
+ else /* STM32H7xx Rev.Y */
+ {
+ hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
+ SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
+ SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
+ SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR);
+
+ hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
+ hsai->Init.DataSize | hsai->Init.FirstBit | \
+ ckstr_bits | syncen_bits | \
+ hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
+ hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
+ hsai->Init.MckOverSampling);
+ }
+#else /* SAI_VER_V2_1*/
+ hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \
+ SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \
+ SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \
+ SAI_xCR1_NODIV | SAI_xCR1_MCKDIV | SAI_xCR1_OSR | \
+ SAI_xCR1_MCKEN);
+
+ hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \
+ hsai->Init.DataSize | hsai->Init.FirstBit | \
+ ckstr_bits | syncen_bits | \
+ hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \
+ hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20) | \
+ hsai->Init.MckOverSampling | hsai->Init.MckOutput);
+#endif /* SAI_VER_V2_X */
+
+ /* SAI CR2 Configuration */
+ hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL);
+ hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState);
+
+ /* SAI Frame Configuration -----------------------------------------*/
+ hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \
+ SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF));
+ hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) |
+ hsai->FrameInit.FSOffset |
+ hsai->FrameInit.FSDefinition |
+ hsai->FrameInit.FSPolarity |
+ ((hsai->FrameInit.ActiveFrameLength - 1U) << 8));
+
+ /* SAI Block_x SLOT Configuration ------------------------------------------*/
+ /* This register has no meaning in AC 97 and SPDIF audio protocol */
+ hsai->Instance->SLOTR &= (~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \
+ SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN));
+
+ hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \
+ (hsai->SlotInit.SlotActive << 16) | ((hsai->SlotInit.SlotNumber - 1U) << 8);
+
+ /* SAI PDM Configuration ---------------------------------------------------*/
+#if defined(SAI4)
+ if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
+#else
+ if (hsai->Instance == SAI1_Block_A)
+#endif /* SAI4 */
+ {
+ /* Disable PDM interface */
+ SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
+ if (hsai->Init.PdmInit.Activation == ENABLE)
+ {
+ /* Configure and enable PDM interface */
+ SaiBaseAddress->PDMCR = (hsai->Init.PdmInit.ClockEnable |
+ ((hsai->Init.PdmInit.MicPairsNbr - 1U) << SAI_PDMCR_MICNBR_Pos));
+ SaiBaseAddress->PDMCR |= SAI_PDMCR_PDMEN;
+ }
+ }
+
+ /* Initialize the error code */
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+
+ /* Initialize the SAI state */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the SAI peripheral.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai)
+{
+ SAI_TypeDef *SaiBaseAddress;
+
+ /* Check the SAI handle allocation */
+ if (hsai == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ hsai->State = HAL_SAI_STATE_BUSY;
+
+ /* Disabled All interrupt and clear all the flag */
+ hsai->Instance->IMR = 0;
+ hsai->Instance->CLRFR = 0xFFFFFFFFU;
+
+ /* Disable the SAI */
+ if (SAI_Disable(hsai) != HAL_OK)
+ {
+ /* Reset SAI state to ready */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_ERROR;
+ }
+
+ /* Flush the fifo */
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
+
+ /* Disable SAI PDM interface */
+#if defined(SAI4)
+ if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI4_Block_A))
+#else
+ if (hsai->Instance == SAI1_Block_A)
+#endif /* SAI4 */
+ {
+ /* Get the SAI base address according to the SAI handle */
+#if defined(SAI4)
+ SaiBaseAddress = (hsai->Instance == SAI1_Block_A) ? SAI1 : SAI4;
+#else
+ SaiBaseAddress = SAI1;
+#endif /* SAI4 */
+
+ /* Reset PDM delays */
+ SaiBaseAddress->PDMDLY = 0U;
+
+ /* Disable PDM interface */
+ SaiBaseAddress->PDMCR &= ~(SAI_PDMCR_PDMEN);
+ }
+
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ if (hsai->MspDeInitCallback == NULL)
+ {
+ hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
+ }
+ hsai->MspDeInitCallback(hsai);
+#else
+ HAL_SAI_MspDeInit(hsai);
+#endif
+
+ /* Initialize the error code */
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+
+ /* Initialize the SAI state */
+ hsai->State = HAL_SAI_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the SAI MSP.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitialize the SAI MSP.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_MspDeInit could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a user SAI callback
+ * to be used instead of the weak predefined callback.
+ * @param hsai SAI handle.
+ * @param CallbackID ID of the callback to be registered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
+ * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
+ * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
+ * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
+ * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @param pCallback pointer to the callback function.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai,
+ HAL_SAI_CallbackIDTypeDef CallbackID,
+ pSAI_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ else
+ {
+ if (HAL_SAI_STATE_READY == hsai->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SAI_RX_COMPLETE_CB_ID :
+ hsai->RxCpltCallback = pCallback;
+ break;
+ case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
+ hsai->RxHalfCpltCallback = pCallback;
+ break;
+ case HAL_SAI_TX_COMPLETE_CB_ID :
+ hsai->TxCpltCallback = pCallback;
+ break;
+ case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
+ hsai->TxHalfCpltCallback = pCallback;
+ break;
+ case HAL_SAI_ERROR_CB_ID :
+ hsai->ErrorCallback = pCallback;
+ break;
+ case HAL_SAI_MSPINIT_CB_ID :
+ hsai->MspInitCallback = pCallback;
+ break;
+ case HAL_SAI_MSPDEINIT_CB_ID :
+ hsai->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SAI_STATE_RESET == hsai->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SAI_MSPINIT_CB_ID :
+ hsai->MspInitCallback = pCallback;
+ break;
+ case HAL_SAI_MSPDEINIT_CB_ID :
+ hsai->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unregister a user SAI callback.
+ * SAI callback is redirected to the weak predefined callback.
+ * @param hsai SAI handle.
+ * @param CallbackID ID of the callback to be unregistered.
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID.
+ * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID.
+ * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID.
+ * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID.
+ * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID.
+ * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID.
+ * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID.
+ * @retval HAL status.
+ */
+HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai,
+ HAL_SAI_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (HAL_SAI_STATE_READY == hsai->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SAI_RX_COMPLETE_CB_ID :
+ hsai->RxCpltCallback = HAL_SAI_RxCpltCallback;
+ break;
+ case HAL_SAI_RX_HALFCOMPLETE_CB_ID :
+ hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback;
+ break;
+ case HAL_SAI_TX_COMPLETE_CB_ID :
+ hsai->TxCpltCallback = HAL_SAI_TxCpltCallback;
+ break;
+ case HAL_SAI_TX_HALFCOMPLETE_CB_ID :
+ hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback;
+ break;
+ case HAL_SAI_ERROR_CB_ID :
+ hsai->ErrorCallback = HAL_SAI_ErrorCallback;
+ break;
+ case HAL_SAI_MSPINIT_CB_ID :
+ hsai->MspInitCallback = HAL_SAI_MspInit;
+ break;
+ case HAL_SAI_MSPDEINIT_CB_ID :
+ hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (HAL_SAI_STATE_RESET == hsai->State)
+ {
+ switch (CallbackID)
+ {
+ case HAL_SAI_MSPINIT_CB_ID :
+ hsai->MspInitCallback = HAL_SAI_MspInit;
+ break;
+ case HAL_SAI_MSPDEINIT_CB_ID :
+ hsai->MspDeInitCallback = HAL_SAI_MspDeInit;
+ break;
+ default :
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update the error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK;
+ /* update return status */
+ status = HAL_ERROR;
+ }
+ return status;
+}
+#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup SAI_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 SAI 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 SAI IRQ when using Interrupt mode or the DMA IRQ when
+ using DMA mode.
+
+ (+) Blocking mode functions are :
+ (++) HAL_SAI_Transmit()
+ (++) HAL_SAI_Receive()
+
+ (+) Non Blocking mode functions with Interrupt are :
+ (++) HAL_SAI_Transmit_IT()
+ (++) HAL_SAI_Receive_IT()
+
+ (+) Non Blocking mode functions with DMA are :
+ (++) HAL_SAI_Transmit_DMA()
+ (++) HAL_SAI_Receive_DMA()
+
+ (+) A set of Transfer Complete Callbacks are provided in non Blocking mode:
+ (++) HAL_SAI_TxCpltCallback()
+ (++) HAL_SAI_RxCpltCallback()
+ (++) HAL_SAI_ErrorCallback()
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Transmit an amount of data in blocking mode.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI 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_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t temp;
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ hsai->XferSize = Size;
+ hsai->XferCount = Size;
+ hsai->pBuffPtr = pData;
+ hsai->State = HAL_SAI_STATE_BUSY_TX;
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+
+ /* Check if the SAI is already enabled */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* fill the fifo with data before to enabled the SAI */
+ SAI_FillFifo(hsai);
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+
+ while (hsai->XferCount > 0U)
+ {
+ /* Write data if the FIFO is not full */
+ if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL)
+ {
+ if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
+ {
+ hsai->Instance->DR = *hsai->pBuffPtr;
+ hsai->pBuffPtr++;
+ }
+ else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
+ {
+ temp = (uint32_t)(*hsai->pBuffPtr);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
+ hsai->pBuffPtr++;
+ hsai->Instance->DR = temp;
+ }
+ else
+ {
+ temp = (uint32_t)(*hsai->pBuffPtr);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
+ hsai->pBuffPtr++;
+ hsai->Instance->DR = temp;
+ }
+ hsai->XferCount--;
+ }
+ else
+ {
+ /* Check for the Timeout */
+ if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
+ {
+ /* Update error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
+
+ /* Clear all the flags */
+ hsai->Instance->CLRFR = 0xFFFFFFFFU;
+
+ /* Disable SAI peripheral */
+ /* No need to check return value because state update, unlock and error return will be performed later */
+ (void) SAI_Disable(hsai);
+
+ /* Flush the fifo */
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
+
+ /* Change the SAI state */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in blocking mode.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI 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_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout)
+{
+ uint32_t tickstart = HAL_GetTick();
+ uint32_t temp;
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ hsai->pBuffPtr = pData;
+ hsai->XferSize = Size;
+ hsai->XferCount = Size;
+ hsai->State = HAL_SAI_STATE_BUSY_RX;
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+
+ /* Check if the SAI is already enabled */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+
+ /* Receive data */
+ while (hsai->XferCount > 0U)
+ {
+ if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY)
+ {
+ if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
+ {
+ *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
+ hsai->pBuffPtr++;
+ }
+ else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
+ {
+ temp = hsai->Instance->DR;
+ *hsai->pBuffPtr = (uint8_t)temp;
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 8);
+ hsai->pBuffPtr++;
+ }
+ else
+ {
+ temp = hsai->Instance->DR;
+ *hsai->pBuffPtr = (uint8_t)temp;
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 8);
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 16);
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 24);
+ hsai->pBuffPtr++;
+ }
+ hsai->XferCount--;
+ }
+ else
+ {
+ /* Check for the Timeout */
+ if ((((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) && (Timeout != HAL_MAX_DELAY))
+ {
+ /* Update error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
+
+ /* Clear all the flags */
+ hsai->Instance->CLRFR = 0xFFFFFFFFU;
+
+ /* Disable SAI peripheral */
+ /* No need to check return value because state update, unlock and error return will be performed later */
+ (void) SAI_Disable(hsai);
+
+ /* Flush the fifo */
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
+
+ /* Change the SAI state */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_ERROR;
+ }
+ }
+ }
+
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with Interrupt.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
+{
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ hsai->pBuffPtr = pData;
+ hsai->XferSize = Size;
+ hsai->XferCount = Size;
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+ hsai->State = HAL_SAI_STATE_BUSY_TX;
+
+ if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
+ {
+ hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit;
+ }
+ else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
+ {
+ hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit;
+ }
+ else
+ {
+ hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit;
+ }
+
+ /* Fill the fifo before starting the communication */
+ SAI_FillFifo(hsai);
+
+ /* Enable FRQ and OVRUDR interrupts */
+ __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+
+ /* Check if the SAI is already enabled */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with Interrupt.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
+{
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ hsai->pBuffPtr = pData;
+ hsai->XferSize = Size;
+ hsai->XferCount = Size;
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+ hsai->State = HAL_SAI_STATE_BUSY_RX;
+
+ if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
+ {
+ hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit;
+ }
+ else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
+ {
+ hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit;
+ }
+ else
+ {
+ hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit;
+ }
+
+ /* Enable TXE and OVRUDR interrupts */
+ __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+
+ /* Check if the SAI is already enabled */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Pause the audio stream playing from the Media.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai)
+{
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ /* Pause the audio file playing by disabling the SAI DMA requests */
+ hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Resume the audio stream playing from the Media.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai)
+{
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ /* Enable the SAI DMA requests */
+ hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
+
+ /* If the SAI peripheral is still not enabled, enable it */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop the audio stream playing from the Media.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ /* Disable SAI peripheral */
+ if (SAI_Disable(hsai) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Disable the SAI DMA request */
+ hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
+
+ /* Abort the SAI Tx DMA Stream */
+ if ((hsai->State == HAL_SAI_STATE_BUSY_TX) && (hsai->hdmatx != NULL))
+ {
+ if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
+ {
+ /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
+ if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
+ {
+ status = HAL_ERROR;
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+ }
+ }
+ }
+
+ /* Abort the SAI Rx DMA Stream */
+ if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
+ {
+ if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
+ {
+ /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
+ if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
+ {
+ status = HAL_ERROR;
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+ }
+ }
+ }
+
+ /* Flush the fifo */
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
+
+ /* Set hsai state to ready */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return status;
+}
+
+/**
+ * @brief Abort the current transfer and disable the SAI.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ /* Disable SAI peripheral */
+ if (SAI_Disable(hsai) != HAL_OK)
+ {
+ status = HAL_ERROR;
+ }
+
+ /* Check SAI DMA is enabled or not */
+ if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
+ {
+ /* Disable the SAI DMA request */
+ hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
+
+ /* Abort the SAI Tx DMA Stream */
+ if ((hsai->State == HAL_SAI_STATE_BUSY_TX)&& (hsai->hdmatx != NULL))
+ {
+ if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK)
+ {
+ /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */
+ if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
+ {
+ status = HAL_ERROR;
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+ }
+ }
+ }
+
+ /* Abort the SAI Rx DMA Stream */
+ if ((hsai->State == HAL_SAI_STATE_BUSY_RX) && (hsai->hdmarx != NULL))
+ {
+ if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK)
+ {
+ /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */
+ if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER)
+ {
+ status = HAL_ERROR;
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+ }
+ }
+ }
+ }
+
+ /* Disabled All interrupt and clear all the flag */
+ hsai->Instance->IMR = 0;
+ hsai->Instance->CLRFR = 0xFFFFFFFFU;
+
+ /* Flush the fifo */
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
+
+ /* Set hsai state to ready */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return status;
+}
+
+/**
+ * @brief Transmit an amount of data in non-blocking mode with DMA.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be sent
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
+{
+ uint32_t tickstart = HAL_GetTick();
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ hsai->pBuffPtr = pData;
+ hsai->XferSize = Size;
+ hsai->XferCount = Size;
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+ hsai->State = HAL_SAI_STATE_BUSY_TX;
+
+ /* Set the SAI Tx DMA Half transfer complete callback */
+ hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt;
+
+ /* Set the SAI TxDMA transfer complete callback */
+ hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt;
+
+ /* Set the DMA error callback */
+ hsai->hdmatx->XferErrorCallback = SAI_DMAError;
+
+ /* Set the DMA Tx abort callback */
+ hsai->hdmatx->XferAbortCallback = NULL;
+
+ /* Enable the Tx DMA Stream */
+ if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK)
+ {
+ __HAL_UNLOCK(hsai);
+ return HAL_ERROR;
+ }
+
+ /* Enable the interrupts for error handling */
+ __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
+
+ /* Enable SAI Tx DMA Request */
+ hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
+
+ /* Wait until FIFO is not empty */
+ while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY)
+ {
+ /* Check for the Timeout */
+ if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT)
+ {
+ /* Update error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_TIMEOUT;
+ }
+ }
+
+ /* Check if the SAI is already enabled */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in non-blocking mode with DMA.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param pData Pointer to data buffer
+ * @param Size Amount of data to be received
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)
+{
+
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsai->State == HAL_SAI_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsai);
+
+ hsai->pBuffPtr = pData;
+ hsai->XferSize = Size;
+ hsai->XferCount = Size;
+ hsai->ErrorCode = HAL_SAI_ERROR_NONE;
+ hsai->State = HAL_SAI_STATE_BUSY_RX;
+
+ /* Set the SAI Rx DMA Half transfer complete callback */
+ hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt;
+
+ /* Set the SAI Rx DMA transfer complete callback */
+ hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt;
+
+ /* Set the DMA error callback */
+ hsai->hdmarx->XferErrorCallback = SAI_DMAError;
+
+ /* Set the DMA Rx abort callback */
+ hsai->hdmarx->XferAbortCallback = NULL;
+
+ /* Enable the Rx DMA Stream */
+ if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK)
+ {
+ __HAL_UNLOCK(hsai);
+ return HAL_ERROR;
+ }
+
+ /* Enable the interrupts for error handling */
+ __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
+
+ /* Enable SAI Rx DMA Request */
+ hsai->Instance->CR1 |= SAI_xCR1_DMAEN;
+
+ /* Check if the SAI is already enabled */
+ if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U)
+ {
+ /* Enable SAI peripheral */
+ __HAL_SAI_ENABLE(hsai);
+ }
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsai);
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Enable the Tx mute mode.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param val value sent during the mute @ref SAI_Block_Mute_Value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val)
+{
+ assert_param(IS_SAI_BLOCK_MUTE_VALUE(val));
+
+ if (hsai->State != HAL_SAI_STATE_RESET)
+ {
+ CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | (uint32_t)val);
+ return HAL_OK;
+ }
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Disable the Tx mute mode.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai)
+{
+ if (hsai->State != HAL_SAI_STATE_RESET)
+ {
+ CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE);
+ return HAL_OK;
+ }
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Enable the Rx mute detection.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param callback function called when the mute is detected.
+ * @param counter number a data before mute detection max 63.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter)
+{
+ assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter));
+
+ if (hsai->State != HAL_SAI_STATE_RESET)
+ {
+ /* set the mute counter */
+ CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT);
+ SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos));
+ hsai->mutecallback = callback;
+ /* enable the IT interrupt */
+ __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET);
+ return HAL_OK;
+ }
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Disable the Rx mute detection.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai)
+{
+ if (hsai->State != HAL_SAI_STATE_RESET)
+ {
+ /* set the mutecallback to NULL */
+ hsai->mutecallback = NULL;
+ /* enable the IT interrupt */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET);
+ return HAL_OK;
+ }
+ return HAL_ERROR;
+}
+
+/**
+ * @brief Handle SAI interrupt request.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai)
+{
+ if (hsai->State != HAL_SAI_STATE_RESET)
+ {
+ uint32_t itflags = hsai->Instance->SR;
+ uint32_t itsources = hsai->Instance->IMR;
+ uint32_t cr1config = hsai->Instance->CR1;
+ uint32_t tmperror;
+
+ /* SAI Fifo request interrupt occurred ------------------------------------*/
+ if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ))
+ {
+ hsai->InterruptServiceRoutine(hsai);
+ }
+ /* SAI Overrun error interrupt occurred ----------------------------------*/
+ else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR))
+ {
+ /* Clear the SAI Overrun flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
+ /* Get the SAI error code */
+ tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR);
+ /* Change the SAI error code */
+ hsai->ErrorCode |= tmperror;
+ /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ /* SAI mutedet interrupt occurred ----------------------------------*/
+ else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET))
+ {
+ /* Clear the SAI mutedet flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET);
+ /* call the call back function */
+ if (hsai->mutecallback != NULL)
+ {
+ /* inform the user that an RX mute event has been detected */
+ hsai->mutecallback();
+ }
+ }
+ /* SAI AFSDET interrupt occurred ----------------------------------*/
+ else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET))
+ {
+ /* Clear the SAI AFSDET flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET);
+
+ /* Change the SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET;
+
+ /* Check SAI DMA is enabled or not */
+ if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
+ {
+ /* Abort the SAI DMA Streams */
+ if (hsai->hdmatx != NULL)
+ {
+ /* Set the DMA Tx abort callback */
+ hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
+
+ /* Abort DMA in IT mode */
+ if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
+ {
+ /* Update SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Call SAI error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ if (hsai->hdmarx != NULL)
+ {
+ /* Set the DMA Rx abort callback */
+ hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
+
+ /* Abort DMA in IT mode */
+ if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
+ {
+ /* Update SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Call SAI error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ }
+ else
+ {
+ /* Abort SAI */
+ /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
+ (void) HAL_SAI_Abort(hsai);
+
+ /* Set error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ /* SAI LFSDET interrupt occurred ----------------------------------*/
+ else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET))
+ {
+ /* Clear the SAI LFSDET flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET);
+
+ /* Change the SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET;
+
+ /* Check SAI DMA is enabled or not */
+ if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
+ {
+ /* Abort the SAI DMA Streams */
+ if (hsai->hdmatx != NULL)
+ {
+ /* Set the DMA Tx abort callback */
+ hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
+
+ /* Abort DMA in IT mode */
+ if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
+ {
+ /* Update SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Call SAI error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ if (hsai->hdmarx != NULL)
+ {
+ /* Set the DMA Rx abort callback */
+ hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
+
+ /* Abort DMA in IT mode */
+ if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
+ {
+ /* Update SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Call SAI error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ }
+ else
+ {
+ /* Abort SAI */
+ /* No need to check return value because HAL_SAI_ErrorCallback will be called later */
+ (void) HAL_SAI_Abort(hsai);
+
+ /* Set error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ /* SAI WCKCFG interrupt occurred ----------------------------------*/
+ else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG))
+ {
+ /* Clear the SAI WCKCFG flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG);
+
+ /* Change the SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG;
+
+ /* Check SAI DMA is enabled or not */
+ if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN)
+ {
+ /* Abort the SAI DMA Streams */
+ if (hsai->hdmatx != NULL)
+ {
+ /* Set the DMA Tx abort callback */
+ hsai->hdmatx->XferAbortCallback = SAI_DMAAbort;
+
+ /* Abort DMA in IT mode */
+ if (HAL_DMA_Abort_IT(hsai->hdmatx) != HAL_OK)
+ {
+ /* Update SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Call SAI error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ if (hsai->hdmarx != NULL)
+ {
+ /* Set the DMA Rx abort callback */
+ hsai->hdmarx->XferAbortCallback = SAI_DMAAbort;
+
+ /* Abort DMA in IT mode */
+ if (HAL_DMA_Abort_IT(hsai->hdmarx) != HAL_OK)
+ {
+ /* Update SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Call SAI error callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ }
+ else
+ {
+ /* If WCKCFG occurs, SAI audio block is automatically disabled */
+ /* Disable all interrupts and clear all flags */
+ hsai->Instance->IMR = 0U;
+ hsai->Instance->CLRFR = 0xFFFFFFFFU;
+ /* Set the SAI state to ready to be able to start again the process */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Initialize XferCount */
+ hsai->XferCount = 0U;
+
+ /* SAI error Callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ }
+ /* SAI CNRDY interrupt occurred ----------------------------------*/
+ else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY))
+ {
+ /* Clear the SAI CNRDY flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY);
+ /* Change the SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY;
+ /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+ else
+ {
+ /* Nothing to do */
+ }
+ }
+}
+
+/**
+ * @brief Tx Transfer completed callback.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_TxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Tx Transfer Half completed callback.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_TxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer completed callback.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_RxCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Rx Transfer half completed callback.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_RxHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SAI error callback.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+__weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsai);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_SAI_ErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SAI_Exported_Functions_Group3 Peripheral State 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 SAI handle state.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval HAL state
+ */
+HAL_SAI_StateTypeDef HAL_SAI_GetState(const SAI_HandleTypeDef *hsai)
+{
+ return hsai->State;
+}
+
+/**
+ * @brief Return the SAI error code.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for the specified SAI Block.
+ * @retval SAI Error Code
+ */
+uint32_t HAL_SAI_GetError(const SAI_HandleTypeDef *hsai)
+{
+ return hsai->ErrorCode;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SAI_Private_Functions
+ * @brief Private functions
+ * @{
+ */
+
+/**
+ * @brief Initialize the SAI I2S protocol according to the specified parameters
+ * in the SAI_InitTypeDef and create the associated handle.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param protocol one of the supported protocol.
+ * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize.
+ * @param nbslot number of slot minimum value is 2 and max is 16.
+ * the value must be a multiple of 2.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ hsai->Init.Protocol = SAI_FREE_PROTOCOL;
+ hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
+ /* Compute ClockStrobing according AudioMode */
+ if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
+ {
+ /* Transmit */
+ hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
+ }
+ else
+ {
+ /* Receive */
+ hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+ }
+ hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+ hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
+ hsai->SlotInit.FirstBitOffset = 0;
+ hsai->SlotInit.SlotNumber = nbslot;
+
+ /* in IS2 the number of slot must be even */
+ if ((nbslot & 0x1U) != 0U)
+ {
+ return HAL_ERROR;
+ }
+
+ if (protocol == SAI_I2S_STANDARD)
+ {
+ hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+ hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+ }
+ else
+ {
+ /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */
+ hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
+ hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT;
+ }
+
+ /* Frame definition */
+ switch (datasize)
+ {
+ case SAI_PROTOCOL_DATASIZE_16BIT:
+ hsai->Init.DataSize = SAI_DATASIZE_16;
+ hsai->FrameInit.FrameLength = 32U * (nbslot / 2U);
+ hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U);
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
+ break;
+ case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
+ hsai->Init.DataSize = SAI_DATASIZE_16;
+ hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
+ hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
+ break;
+ case SAI_PROTOCOL_DATASIZE_24BIT:
+ hsai->Init.DataSize = SAI_DATASIZE_24;
+ hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
+ hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
+ break;
+ case SAI_PROTOCOL_DATASIZE_32BIT:
+ hsai->Init.DataSize = SAI_DATASIZE_32;
+ hsai->FrameInit.FrameLength = 64U * (nbslot / 2U);
+ hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U);
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
+ break;
+ default :
+ status = HAL_ERROR;
+ break;
+ }
+ if (protocol == SAI_I2S_LSBJUSTIFIED)
+ {
+ if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED)
+ {
+ hsai->SlotInit.FirstBitOffset = 16;
+ }
+ if (datasize == SAI_PROTOCOL_DATASIZE_24BIT)
+ {
+ hsai->SlotInit.FirstBitOffset = 8;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Initialize the SAI PCM protocol according to the specified parameters
+ * in the SAI_InitTypeDef and create the associated handle.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param protocol one of the supported protocol
+ * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize
+ * @param nbslot number of slot minimum value is 1 and the max is 16.
+ * @retval HAL status
+ */
+static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ hsai->Init.Protocol = SAI_FREE_PROTOCOL;
+ hsai->Init.FirstBit = SAI_FIRSTBIT_MSB;
+ /* Compute ClockStrobing according AudioMode */
+ if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
+ {
+ /* Transmit */
+ hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+ }
+ else
+ {
+ /* Receive */
+ hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
+ }
+ hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME;
+ hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH;
+ hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+ hsai->SlotInit.FirstBitOffset = 0;
+ hsai->SlotInit.SlotNumber = nbslot;
+ hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL;
+
+ if (protocol == SAI_PCM_SHORT)
+ {
+ hsai->FrameInit.ActiveFrameLength = 1;
+ }
+ else
+ {
+ /* SAI_PCM_LONG */
+ hsai->FrameInit.ActiveFrameLength = 13;
+ }
+
+ switch (datasize)
+ {
+ case SAI_PROTOCOL_DATASIZE_16BIT:
+ hsai->Init.DataSize = SAI_DATASIZE_16;
+ hsai->FrameInit.FrameLength = 16U * nbslot;
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B;
+ break;
+ case SAI_PROTOCOL_DATASIZE_16BITEXTENDED :
+ hsai->Init.DataSize = SAI_DATASIZE_16;
+ hsai->FrameInit.FrameLength = 32U * nbslot;
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
+ break;
+ case SAI_PROTOCOL_DATASIZE_24BIT :
+ hsai->Init.DataSize = SAI_DATASIZE_24;
+ hsai->FrameInit.FrameLength = 32U * nbslot;
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
+ break;
+ case SAI_PROTOCOL_DATASIZE_32BIT:
+ hsai->Init.DataSize = SAI_DATASIZE_32;
+ hsai->FrameInit.FrameLength = 32U * nbslot;
+ hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B;
+ break;
+ default :
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Fill the fifo.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_FillFifo(SAI_HandleTypeDef *hsai)
+{
+ uint32_t temp;
+
+ /* fill the fifo with data before to enabled the SAI */
+ while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U))
+ {
+ if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING))
+ {
+ hsai->Instance->DR = *hsai->pBuffPtr;
+ hsai->pBuffPtr++;
+ }
+ else if (hsai->Init.DataSize <= SAI_DATASIZE_16)
+ {
+ temp = (uint32_t)(*hsai->pBuffPtr);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
+ hsai->pBuffPtr++;
+ hsai->Instance->DR = temp;
+ }
+ else
+ {
+ temp = (uint32_t)(*hsai->pBuffPtr);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
+ hsai->pBuffPtr++;
+ hsai->Instance->DR = temp;
+ }
+ hsai->XferCount--;
+ }
+}
+
+/**
+ * @brief Return the interrupt flag to set according the SAI setup.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @param mode SAI_MODE_DMA or SAI_MODE_IT
+ * @retval the list of the IT flag to enable
+ */
+static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, SAI_ModeTypedef mode)
+{
+ uint32_t tmpIT = SAI_IT_OVRUDR;
+
+ if (mode == SAI_MODE_IT)
+ {
+ tmpIT |= SAI_IT_FREQ;
+ }
+
+ if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) &&
+ ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX)))
+ {
+ tmpIT |= SAI_IT_CNRDY;
+ }
+
+ if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
+ {
+ tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET;
+ }
+ else
+ {
+ /* hsai has been configured in master mode */
+ tmpIT |= SAI_IT_WCKCFG;
+ }
+ return tmpIT;
+}
+
+/**
+ * @brief Disable the SAI and wait for the disabling.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
+{
+ uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Disable the SAI instance */
+ __HAL_SAI_DISABLE(hsai);
+
+ do
+ {
+ /* Check for the Timeout */
+ if (count == 0U)
+ {
+ /* Update error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
+ status = HAL_TIMEOUT;
+ break;
+ }
+ count--;
+ }
+ while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);
+
+ return status;
+}
+
+/**
+ * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai)
+{
+ if (hsai->XferCount == 0U)
+ {
+ /* Handle the end of the transmission */
+ /* Disable FREQ and OVRUDR interrupts */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+ hsai->State = HAL_SAI_STATE_READY;
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->TxCpltCallback(hsai);
+#else
+ HAL_SAI_TxCpltCallback(hsai);
+#endif
+ }
+ else
+ {
+ /* Write data on DR register */
+ hsai->Instance->DR = *hsai->pBuffPtr;
+ hsai->pBuffPtr++;
+ hsai->XferCount--;
+ }
+}
+
+/**
+ * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai)
+{
+ if (hsai->XferCount == 0U)
+ {
+ /* Handle the end of the transmission */
+ /* Disable FREQ and OVRUDR interrupts */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+ hsai->State = HAL_SAI_STATE_READY;
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->TxCpltCallback(hsai);
+#else
+ HAL_SAI_TxCpltCallback(hsai);
+#endif
+ }
+ else
+ {
+ /* Write data on DR register */
+ uint32_t temp;
+ temp = (uint32_t)(*hsai->pBuffPtr);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
+ hsai->pBuffPtr++;
+ hsai->Instance->DR = temp;
+ hsai->XferCount--;
+ }
+}
+
+/**
+ * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai)
+{
+ if (hsai->XferCount == 0U)
+ {
+ /* Handle the end of the transmission */
+ /* Disable FREQ and OVRUDR interrupts */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+ hsai->State = HAL_SAI_STATE_READY;
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->TxCpltCallback(hsai);
+#else
+ HAL_SAI_TxCpltCallback(hsai);
+#endif
+ }
+ else
+ {
+ /* Write data on DR register */
+ uint32_t temp;
+ temp = (uint32_t)(*hsai->pBuffPtr);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 8);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 16);
+ hsai->pBuffPtr++;
+ temp |= ((uint32_t)(*hsai->pBuffPtr) << 24);
+ hsai->pBuffPtr++;
+ hsai->Instance->DR = temp;
+ hsai->XferCount--;
+ }
+}
+
+/**
+ * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai)
+{
+ /* Receive data */
+ *hsai->pBuffPtr = (uint8_t)hsai->Instance->DR;
+ hsai->pBuffPtr++;
+ hsai->XferCount--;
+
+ /* Check end of the transfer */
+ if (hsai->XferCount == 0U)
+ {
+ /* Disable TXE and OVRUDR interrupts */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+
+ /* Clear the SAI Overrun flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
+
+ hsai->State = HAL_SAI_STATE_READY;
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->RxCpltCallback(hsai);
+#else
+ HAL_SAI_RxCpltCallback(hsai);
+#endif
+ }
+}
+
+/**
+ * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai)
+{
+ uint32_t temp;
+
+ /* Receive data */
+ temp = hsai->Instance->DR;
+ *hsai->pBuffPtr = (uint8_t)temp;
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 8);
+ hsai->pBuffPtr++;
+ hsai->XferCount--;
+
+ /* Check end of the transfer */
+ if (hsai->XferCount == 0U)
+ {
+ /* Disable TXE and OVRUDR interrupts */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+
+ /* Clear the SAI Overrun flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
+
+ hsai->State = HAL_SAI_STATE_READY;
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->RxCpltCallback(hsai);
+#else
+ HAL_SAI_RxCpltCallback(hsai);
+#endif
+ }
+}
+
+/**
+ * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer.
+ * @param hsai pointer to a SAI_HandleTypeDef structure that contains
+ * the configuration information for SAI module.
+ * @retval None
+ */
+static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai)
+{
+ uint32_t temp;
+
+ /* Receive data */
+ temp = hsai->Instance->DR;
+ *hsai->pBuffPtr = (uint8_t)temp;
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 8);
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 16);
+ hsai->pBuffPtr++;
+ *hsai->pBuffPtr = (uint8_t)(temp >> 24);
+ hsai->pBuffPtr++;
+ hsai->XferCount--;
+
+ /* Check end of the transfer */
+ if (hsai->XferCount == 0U)
+ {
+ /* Disable TXE and OVRUDR interrupts */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT));
+
+ /* Clear the SAI Overrun flag */
+ __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR);
+
+ hsai->State = HAL_SAI_STATE_READY;
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->RxCpltCallback(hsai);
+#else
+ HAL_SAI_RxCpltCallback(hsai);
+#endif
+ }
+}
+
+/**
+ * @brief DMA SAI 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 SAI_DMATxCplt(DMA_HandleTypeDef *hdma)
+{
+ SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ hsai->XferCount = 0;
+
+ /* Disable SAI Tx DMA Request */
+ hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
+
+ /* Stop the interrupts error handling */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
+
+ hsai->State = HAL_SAI_STATE_READY;
+ }
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->TxCpltCallback(hsai);
+#else
+ HAL_SAI_TxCpltCallback(hsai);
+#endif
+}
+
+/**
+ * @brief DMA SAI 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 SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->TxHalfCpltCallback(hsai);
+#else
+ HAL_SAI_TxHalfCpltCallback(hsai);
+#endif
+}
+
+/**
+ * @brief DMA SAI 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 SAI_DMARxCplt(DMA_HandleTypeDef *hdma)
+{
+ SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma->Init.Mode != DMA_CIRCULAR)
+ {
+ /* Disable Rx DMA Request */
+ hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN);
+ hsai->XferCount = 0;
+
+ /* Stop the interrupts error handling */
+ __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA));
+
+ hsai->State = HAL_SAI_STATE_READY;
+ }
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->RxCpltCallback(hsai);
+#else
+ HAL_SAI_RxCpltCallback(hsai);
+#endif
+}
+
+/**
+ * @brief DMA SAI 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 SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->RxHalfCpltCallback(hsai);
+#else
+ HAL_SAI_RxHalfCpltCallback(hsai);
+#endif
+}
+
+/**
+ * @brief DMA SAI 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 SAI_DMAError(DMA_HandleTypeDef *hdma)
+{
+ SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Ignore DMA FIFO error */
+ if (HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
+ {
+ /* Set SAI error code */
+ hsai->ErrorCode |= HAL_SAI_ERROR_DMA;
+
+ /* Disable the SAI DMA request */
+ hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
+
+ /* Disable SAI peripheral */
+ /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
+ (void) SAI_Disable(hsai);
+
+ /* Set the SAI state ready to be able to start again the process */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Initialize XferCount */
+ hsai->XferCount = 0U;
+
+ /* SAI error Callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+ }
+}
+
+/**
+ * @brief DMA SAI Abort callback.
+ * @param hdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+static void SAI_DMAAbort(DMA_HandleTypeDef *hdma)
+{
+ SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Disable DMA request */
+ hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN;
+
+ /* Disable all interrupts and clear all flags */
+ hsai->Instance->IMR = 0U;
+ hsai->Instance->CLRFR = 0xFFFFFFFFU;
+
+ if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG)
+ {
+ /* Disable SAI peripheral */
+ /* No need to check return value because state will be updated and HAL_SAI_ErrorCallback will be called later */
+ (void) SAI_Disable(hsai);
+
+ /* Flush the fifo */
+ SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH);
+ }
+ /* Set the SAI state to ready to be able to start again the process */
+ hsai->State = HAL_SAI_STATE_READY;
+
+ /* Initialize XferCount */
+ hsai->XferCount = 0U;
+
+ /* SAI error Callback */
+#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1)
+ hsai->ErrorCallback(hsai);
+#else
+ HAL_SAI_ErrorCallback(hsai);
+#endif
+}
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SAI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai_ex.c
new file mode 100755
index 0000000..a48bb67
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sai_ex.c
@@ -0,0 +1,134 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_sai_ex.c
+ * @author MCD Application Team
+ * @brief SAI Extended HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionality of the SAI Peripheral Controller:
+ * + Modify PDM microphone delays.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#ifdef HAL_SAI_MODULE_ENABLED
+
+/** @defgroup SAIEx SAIEx
+ * @brief SAI Extended HAL module driver
+ * @{
+ */
+
+/* Private types -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private constants ---------------------------------------------------------*/
+#define SAI_PDM_DELAY_MASK 0x77UL
+#define SAI_PDM_DELAY_OFFSET 8U
+#define SAI_PDM_RIGHT_DELAY_OFFSET 4U
+
+/* Private macros ------------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SAIEx_Exported_Functions SAIEx Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup SAIEx_Exported_Functions_Group1 Peripheral Control functions
+ * @brief SAIEx control functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Extended features functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+ (+) Modify PDM microphone delays
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure PDM microphone delays.
+ * @param hsai SAI handle.
+ * @param pdmMicDelay Microphone delays configuration.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SAIEx_ConfigPdmMicDelay(const SAI_HandleTypeDef *hsai,
+ const SAIEx_PdmMicDelayParamTypeDef *pdmMicDelay)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t offset;
+ SAI_TypeDef *SaiBaseAddress;
+
+ /* Get the SAI base address according to the SAI handle */
+#if defined(SAI4)
+ SaiBaseAddress = ((hsai->Instance == SAI1_Block_A) ? SAI1 : \
+ (hsai->Instance == SAI4_Block_A) ? SAI4 : \
+ NULL);
+#else
+ SaiBaseAddress = ((hsai->Instance == SAI1_Block_A) ? SAI1 : NULL);
+#endif /* SAI4 */
+
+ /* Check that SAI sub-block is SAI sub-block A */
+ if (SaiBaseAddress == NULL)
+ {
+ status = HAL_ERROR;
+ }
+ else
+ {
+ /* Check microphone delay parameters */
+ assert_param(IS_SAI_PDM_MIC_PAIRS_NUMBER(pdmMicDelay->MicPair));
+ assert_param(IS_SAI_PDM_MIC_DELAY(pdmMicDelay->LeftDelay));
+ assert_param(IS_SAI_PDM_MIC_DELAY(pdmMicDelay->RightDelay));
+
+ /* Compute offset on PDMDLY register according mic pair number */
+ offset = SAI_PDM_DELAY_OFFSET * (pdmMicDelay->MicPair - 1U);
+
+ /* Check SAI state and offset */
+ if ((hsai->State != HAL_SAI_STATE_RESET) && (offset <= 24U))
+ {
+ /* Reset current delays for specified microphone */
+ SaiBaseAddress->PDMDLY &= ~(SAI_PDM_DELAY_MASK << offset);
+
+ /* Apply new microphone delays */
+ SaiBaseAddress->PDMDLY |= (((pdmMicDelay->RightDelay << SAI_PDM_RIGHT_DELAY_OFFSET) | pdmMicDelay->LeftDelay) << offset);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+ }
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SAI_MODULE_ENABLED */
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sdram.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sdram.c
new file mode 100755
index 0000000..d376e44
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sdram.c
@@ -0,0 +1,1314 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_sdram.c
+ * @author MCD Application Team
+ * @brief SDRAM HAL module driver.
+ * This file provides a generic firmware to drive SDRAM memories mounted
+ * as external device.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a generic layered driver which contains a set of APIs used to
+ control SDRAM memories. It uses the FMC layer functions to interface
+ with SDRAM devices.
+ The following sequence should be followed to configure the FMC to interface
+ with SDRAM memories:
+
+ (#) Declare a SDRAM_HandleTypeDef handle structure, for example:
+ SDRAM_HandleTypeDef hsdram
+
+ (++) Fill the SDRAM_HandleTypeDef handle "Init" field with the allowed
+ values of the structure member.
+
+ (++) Fill the SDRAM_HandleTypeDef handle "Instance" field with a predefined
+ base register instance for NOR or SDRAM device
+
+ (#) Declare a FMC_SDRAM_TimingTypeDef structure; for example:
+ FMC_SDRAM_TimingTypeDef Timing;
+ and fill its fields with the allowed values of the structure member.
+
+ (#) Initialize the SDRAM Controller by calling the function HAL_SDRAM_Init(). This function
+ performs the following sequence:
+
+ (##) MSP hardware layer configuration using the function HAL_SDRAM_MspInit()
+ (##) Control register configuration using the FMC SDRAM interface function
+ FMC_SDRAM_Init()
+ (##) Timing register configuration using the FMC SDRAM interface function
+ FMC_SDRAM_Timing_Init()
+ (##) Program the SDRAM external device by applying its initialization sequence
+ according to the device plugged in your hardware. This step is mandatory
+ for accessing the SDRAM device.
+
+ (#) At this stage you can perform read/write accesses from/to the memory connected
+ to the SDRAM Bank. You can perform either polling or DMA transfer using the
+ following APIs:
+ (++) HAL_SDRAM_Read()/HAL_SDRAM_Write() for polling read/write access
+ (++) HAL_SDRAM_Read_DMA()/HAL_SDRAM_Write_DMA() for DMA read/write transfer
+
+ (#) You can also control the SDRAM device by calling the control APIs HAL_SDRAM_WriteOperation_Enable()/
+ HAL_SDRAM_WriteOperation_Disable() to respectively enable/disable the SDRAM write operation or
+ the function HAL_SDRAM_SendCommand() to send a specified command to the SDRAM
+ device. The command to be sent must be configured with the FMC_SDRAM_CommandTypeDef
+ structure.
+
+ (#) You can continuously monitor the SDRAM device HAL state by calling the function
+ HAL_SDRAM_GetState()
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_SDRAM_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions HAL_SDRAM_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) MspInitCallback : SDRAM MspInit.
+ (+) MspDeInitCallback : SDRAM MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function HAL_SDRAM_UnRegisterCallback() to reset a callback to the default
+ weak (overridden) function. It allows to reset following callbacks:
+ (+) MspInitCallback : SDRAM MspInit.
+ (+) MspDeInitCallback : SDRAM MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the HAL_SDRAM_Init and if the state is HAL_SDRAM_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (overridden) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (overridden) functions in the HAL_SDRAM_Init
+ and HAL_SDRAM_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_SDRAM_Init and HAL_SDRAM_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in READY state only.
+ Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
+ in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
+ during the Init/DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_SDRAM_RegisterCallback before calling HAL_SDRAM_DeInit
+ or HAL_SDRAM_Init function.
+
+ When The compilation define USE_HAL_SDRAM_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (overridden) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_SDRAM_MODULE_ENABLED
+
+/** @defgroup SDRAM SDRAM
+ * @brief SDRAM driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup SDRAM_Private_Functions SDRAM Private Functions
+ * @{
+ */
+static void SDRAM_DMACplt(MDMA_HandleTypeDef *hmdma);
+static void SDRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma);
+static void SDRAM_DMAError(MDMA_HandleTypeDef *hmdma);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup SDRAM_Exported_Functions SDRAM Exported Functions
+ * @{
+ */
+
+/** @defgroup SDRAM_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### SDRAM Initialization and de_initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to initialize/de-initialize
+ the SDRAM memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Performs the SDRAM device initialization sequence.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param Timing Pointer to SDRAM control timing structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Init(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_TimingTypeDef *Timing)
+{
+ /* Check the SDRAM handle parameter */
+ if (hsdram == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsdram->State == HAL_SDRAM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hsdram->Lock = HAL_UNLOCKED;
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+ if (hsdram->MspInitCallback == NULL)
+ {
+ hsdram->MspInitCallback = HAL_SDRAM_MspInit;
+ }
+ hsdram->RefreshErrorCallback = HAL_SDRAM_RefreshErrorCallback;
+ hsdram->DmaXferCpltCallback = HAL_SDRAM_DMA_XferCpltCallback;
+ hsdram->DmaXferErrorCallback = HAL_SDRAM_DMA_XferErrorCallback;
+
+ /* Init the low level hardware */
+ hsdram->MspInitCallback(hsdram);
+#else
+ /* Initialize the low level hardware (MSP) */
+ HAL_SDRAM_MspInit(hsdram);
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+ }
+
+ /* Initialize the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Initialize SDRAM control Interface */
+ (void)FMC_SDRAM_Init(hsdram->Instance, &(hsdram->Init));
+
+ /* Initialize SDRAM timing Interface */
+ (void)FMC_SDRAM_Timing_Init(hsdram->Instance, Timing, hsdram->Init.SDBank);
+
+ /* Enable FMC Peripheral */
+ __FMC_ENABLE();
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Perform the SDRAM device initialization sequence.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_DeInit(SDRAM_HandleTypeDef *hsdram)
+{
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+ if (hsdram->MspDeInitCallback == NULL)
+ {
+ hsdram->MspDeInitCallback = HAL_SDRAM_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hsdram->MspDeInitCallback(hsdram);
+#else
+ /* Initialize the low level hardware (MSP) */
+ HAL_SDRAM_MspDeInit(hsdram);
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+
+ /* Configure the SDRAM registers with their reset values */
+ (void)FMC_SDRAM_DeInit(hsdram->Instance, hsdram->Init.SDBank);
+
+ /* Reset the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsdram);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief SDRAM MSP Init.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval None
+ */
+__weak void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsdram);
+
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_SDRAM_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SDRAM MSP DeInit.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval None
+ */
+__weak void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef *hsdram)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsdram);
+
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_SDRAM_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief This function handles SDRAM refresh error interrupt request.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval HAL status
+ */
+void HAL_SDRAM_IRQHandler(SDRAM_HandleTypeDef *hsdram)
+{
+ /* Check SDRAM interrupt Rising edge flag */
+ if (__FMC_SDRAM_GET_FLAG(hsdram->Instance, FMC_SDRAM_FLAG_REFRESH_IT))
+ {
+ /* SDRAM refresh error interrupt callback */
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+ hsdram->RefreshErrorCallback(hsdram);
+#else
+ HAL_SDRAM_RefreshErrorCallback(hsdram);
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+
+ /* Clear SDRAM refresh error interrupt pending bit */
+ __FMC_SDRAM_CLEAR_FLAG(hsdram->Instance, FMC_SDRAM_FLAG_REFRESH_ERROR);
+ }
+}
+
+/**
+ * @brief SDRAM Refresh error callback.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval None
+ */
+__weak void HAL_SDRAM_RefreshErrorCallback(SDRAM_HandleTypeDef *hsdram)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsdram);
+
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_SDRAM_RefreshErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA transfer complete callback.
+ * @param hmdma pointer to a DMA_HandleTypeDef structure that contains
+ * the configuration information for the specified DMA module.
+ * @retval None
+ */
+__weak void HAL_SDRAM_DMA_XferCpltCallback(MDMA_HandleTypeDef *hmdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdma);
+
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_SDRAM_DMA_XferCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA transfer complete error callback.
+ * @param hmdma DMA handle
+ * @retval None
+ */
+__weak void HAL_SDRAM_DMA_XferErrorCallback(MDMA_HandleTypeDef *hmdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdma);
+
+ /* NOTE: This function Should not be modified, when the callback is needed,
+ the HAL_SDRAM_DMA_XferErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SDRAM_Exported_Functions_Group2 Input and Output functions
+ * @brief Input Output and memory control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### SDRAM Input and Output functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to use and control the SDRAM memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Reads 8-bit data buffer from the SDRAM memory.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Read_8b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint8_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint8_t *pSdramAddress = (uint8_t *)pAddress;
+ uint8_t *pdestbuff = pDstBuffer;
+ HAL_SDRAM_StateTypeDef state = hsdram->State;
+
+ /* Check the SDRAM controller state */
+ if (state == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Read data from source */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *pdestbuff = *(__IO uint8_t *)pSdramAddress;
+ pdestbuff++;
+ pSdramAddress++;
+ }
+
+ /* Update the SDRAM controller state */
+ hsdram->State = state;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Writes 8-bit data buffer to SDRAM memory.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Write_8b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint8_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint8_t *pSdramAddress = (uint8_t *)pAddress;
+ uint8_t *psrcbuff = pSrcBuffer;
+
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Write data to memory */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *(__IO uint8_t *)pSdramAddress = *psrcbuff;
+ psrcbuff++;
+ pSdramAddress++;
+ }
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads 16-bit data buffer from the SDRAM memory.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Read_16b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint16_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *pSdramAddress = pAddress;
+ uint16_t *pdestbuff = pDstBuffer;
+ HAL_SDRAM_StateTypeDef state = hsdram->State;
+
+ /* Check the SDRAM controller state */
+ if (state == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Read data from memory */
+ for (size = BufferSize; size >= 2U ; size -= 2U)
+ {
+ *pdestbuff = (uint16_t)((*pSdramAddress) & 0x0000FFFFU);
+ pdestbuff++;
+ *pdestbuff = (uint16_t)(((*pSdramAddress) & 0xFFFF0000U) >> 16U);
+ pdestbuff++;
+ pSdramAddress++;
+ }
+
+ /* Read last 16-bits if size is not 32-bits multiple */
+ if ((BufferSize % 2U) != 0U)
+ {
+ *pdestbuff = (uint16_t)((*pSdramAddress) & 0x0000FFFFU);
+ }
+
+ /* Update the SDRAM controller state */
+ hsdram->State = state;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Writes 16-bit data buffer to SDRAM memory.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Write_16b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint16_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *psdramaddress = pAddress;
+ uint16_t *psrcbuff = pSrcBuffer;
+
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Write data to memory */
+ for (size = BufferSize; size >= 2U ; size -= 2U)
+ {
+ *psdramaddress = (uint32_t)(*psrcbuff);
+ psrcbuff++;
+ *psdramaddress |= ((uint32_t)(*psrcbuff) << 16U);
+ psrcbuff++;
+ psdramaddress++;
+ }
+
+ /* Write last 16-bits if size is not 32-bits multiple */
+ if ((BufferSize % 2U) != 0U)
+ {
+ *psdramaddress = ((uint32_t)(*psrcbuff) & 0x0000FFFFU) | ((*psdramaddress) & 0xFFFF0000U);
+ }
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads 32-bit data buffer from the SDRAM memory.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Read_32b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *pSdramAddress = (uint32_t *)pAddress;
+ uint32_t *pdestbuff = pDstBuffer;
+ HAL_SDRAM_StateTypeDef state = hsdram->State;
+
+ /* Check the SDRAM controller state */
+ if (state == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Read data from source */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *pdestbuff = *(__IO uint32_t *)pSdramAddress;
+ pdestbuff++;
+ pSdramAddress++;
+ }
+
+ /* Update the SDRAM controller state */
+ hsdram->State = state;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Writes 32-bit data buffer to SDRAM memory.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Write_32b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *pSdramAddress = pAddress;
+ uint32_t *psrcbuff = pSrcBuffer;
+
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Write data to memory */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *pSdramAddress = *psrcbuff;
+ psrcbuff++;
+ pSdramAddress++;
+ }
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads a Words data from the SDRAM memory using DMA transfer.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Read_DMA(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ HAL_StatusTypeDef status;
+ HAL_SDRAM_StateTypeDef state = hsdram->State;
+
+ /* Check the SDRAM controller state */
+ if (state == HAL_SDRAM_STATE_BUSY)
+ {
+ status = HAL_BUSY;
+ }
+ else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Configure DMA user callbacks */
+ if (state == HAL_SDRAM_STATE_READY)
+ {
+ hsdram->hmdma->XferCpltCallback = SDRAM_DMACplt;
+ }
+ else
+ {
+ hsdram->hmdma->XferCpltCallback = SDRAM_DMACpltProt;
+ }
+ hsdram->hmdma->XferErrorCallback = SDRAM_DMAError;
+
+ /* Enable the DMA Stream */
+ status = HAL_MDMA_Start_IT(hsdram->hmdma, (uint32_t)pAddress, (uint32_t)pDstBuffer, (uint32_t)(BufferSize * 4U), 1);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Writes a Words data buffer to SDRAM memory using DMA transfer.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_Write_DMA(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ status = HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsdram);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Configure DMA user callbacks */
+ hsdram->hmdma->XferCpltCallback = SDRAM_DMACplt;
+ hsdram->hmdma->XferErrorCallback = SDRAM_DMAError;
+
+ /* Enable the DMA Stream */
+ status = HAL_MDMA_Start_IT(hsdram->hmdma, (uint32_t)pSrcBuffer, (uint32_t)pAddress, (uint32_t)(BufferSize * 4U), 1);
+
+ /* Process Unlocked */
+ __HAL_UNLOCK(hsdram);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SDRAM Callback
+ * To be used to override the weak predefined callback
+ * @param hsdram : SDRAM handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SDRAM_MSP_INIT_CB_ID SDRAM MspInit callback ID
+ * @arg @ref HAL_SDRAM_MSP_DEINIT_CB_ID SDRAM MspDeInit callback ID
+ * @arg @ref HAL_SDRAM_REFRESH_ERR_CB_ID SDRAM Refresh Error callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SDRAM_RegisterCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId,
+ pSDRAM_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SDRAM_StateTypeDef state;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ state = hsdram->State;
+ if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_SDRAM_MSP_INIT_CB_ID :
+ hsdram->MspInitCallback = pCallback;
+ break;
+ case HAL_SDRAM_MSP_DEINIT_CB_ID :
+ hsdram->MspDeInitCallback = pCallback;
+ break;
+ case HAL_SDRAM_REFRESH_ERR_CB_ID :
+ hsdram->RefreshErrorCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_SDRAM_MSP_INIT_CB_ID :
+ hsdram->MspInitCallback = pCallback;
+ break;
+ case HAL_SDRAM_MSP_DEINIT_CB_ID :
+ hsdram->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a User SDRAM Callback
+ * SDRAM Callback is redirected to the weak predefined callback
+ * @param hsdram : SDRAM handle
+ * @param CallbackId : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SDRAM_MSP_INIT_CB_ID SDRAM MspInit callback ID
+ * @arg @ref HAL_SDRAM_MSP_DEINIT_CB_ID SDRAM MspDeInit callback ID
+ * @arg @ref HAL_SDRAM_REFRESH_ERR_CB_ID SDRAM Refresh Error callback ID
+ * @arg @ref HAL_SDRAM_DMA_XFER_CPLT_CB_ID SDRAM DMA Xfer Complete callback ID
+ * @arg @ref HAL_SDRAM_DMA_XFER_ERR_CB_ID SDRAM DMA Xfer Error callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SDRAM_UnRegisterCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SDRAM_StateTypeDef state;
+
+ state = hsdram->State;
+ if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_SDRAM_MSP_INIT_CB_ID :
+ hsdram->MspInitCallback = HAL_SDRAM_MspInit;
+ break;
+ case HAL_SDRAM_MSP_DEINIT_CB_ID :
+ hsdram->MspDeInitCallback = HAL_SDRAM_MspDeInit;
+ break;
+ case HAL_SDRAM_REFRESH_ERR_CB_ID :
+ hsdram->RefreshErrorCallback = HAL_SDRAM_RefreshErrorCallback;
+ break;
+ case HAL_SDRAM_DMA_XFER_CPLT_CB_ID :
+ hsdram->DmaXferCpltCallback = HAL_SDRAM_DMA_XferCpltCallback;
+ break;
+ case HAL_SDRAM_DMA_XFER_ERR_CB_ID :
+ hsdram->DmaXferErrorCallback = HAL_SDRAM_DMA_XferErrorCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_SDRAM_MSP_INIT_CB_ID :
+ hsdram->MspInitCallback = HAL_SDRAM_MspInit;
+ break;
+ case HAL_SDRAM_MSP_DEINIT_CB_ID :
+ hsdram->MspDeInitCallback = HAL_SDRAM_MspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register a User SDRAM Callback for DMA transfers
+ * To be used to override the weak predefined callback
+ * @param hsdram : SDRAM handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SDRAM_DMA_XFER_CPLT_CB_ID SDRAM DMA Xfer Complete callback ID
+ * @arg @ref HAL_SDRAM_DMA_XFER_ERR_CB_ID SDRAM DMA Xfer Error callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SDRAM_RegisterDmaCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId,
+ pSDRAM_DmaCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SDRAM_StateTypeDef state;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hsdram);
+
+ state = hsdram->State;
+ if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_SDRAM_DMA_XFER_CPLT_CB_ID :
+ hsdram->DmaXferCpltCallback = pCallback;
+ break;
+ case HAL_SDRAM_DMA_XFER_ERR_CB_ID :
+ hsdram->DmaXferErrorCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsdram);
+ return status;
+}
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup SDRAM_Exported_Functions_Group3 Control functions
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### SDRAM Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the SDRAM interface.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables dynamically SDRAM write protection.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_WriteProtection_Enable(SDRAM_HandleTypeDef *hsdram)
+{
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Enable write protection */
+ (void)FMC_SDRAM_WriteProtection_Enable(hsdram->Instance, hsdram->Init.SDBank);
+
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_WRITE_PROTECTED;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically SDRAM write protection.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_WriteProtection_Disable(SDRAM_HandleTypeDef *hsdram)
+{
+ HAL_SDRAM_StateTypeDef state = hsdram->State;
+
+ /* Check the SDRAM controller state */
+ if (state == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (state == HAL_SDRAM_STATE_WRITE_PROTECTED)
+ {
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Disable write protection */
+ (void)FMC_SDRAM_WriteProtection_Disable(hsdram->Instance, hsdram->Init.SDBank);
+
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sends Command to the SDRAM bank.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param Command SDRAM command structure
+ * @param Timeout Timeout duration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_SendCommand(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command,
+ uint32_t Timeout)
+{
+ HAL_SDRAM_StateTypeDef state = hsdram->State;
+
+ /* Check the SDRAM controller state */
+ if (state == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_PRECHARGED))
+ {
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Send SDRAM command */
+ (void)FMC_SDRAM_SendCommand(hsdram->Instance, Command, Timeout);
+
+ /* Update the SDRAM controller state state */
+ if (Command->CommandMode == FMC_SDRAM_CMD_PALL)
+ {
+ hsdram->State = HAL_SDRAM_STATE_PRECHARGED;
+ }
+ else
+ {
+ hsdram->State = HAL_SDRAM_STATE_READY;
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Programs the SDRAM Memory Refresh rate.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param RefreshRate The SDRAM refresh rate value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_ProgramRefreshRate(SDRAM_HandleTypeDef *hsdram, uint32_t RefreshRate)
+{
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Program the refresh rate */
+ (void)FMC_SDRAM_ProgramRefreshRate(hsdram->Instance, RefreshRate);
+
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Sets the Number of consecutive SDRAM Memory auto Refresh commands.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @param AutoRefreshNumber The SDRAM auto Refresh number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SDRAM_SetAutoRefreshNumber(SDRAM_HandleTypeDef *hsdram, uint32_t AutoRefreshNumber)
+{
+ /* Check the SDRAM controller state */
+ if (hsdram->State == HAL_SDRAM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (hsdram->State == HAL_SDRAM_STATE_READY)
+ {
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_BUSY;
+
+ /* Set the Auto-Refresh number */
+ (void)FMC_SDRAM_SetAutoRefreshNumber(hsdram->Instance, AutoRefreshNumber);
+
+ /* Update the SDRAM state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Returns the SDRAM memory current mode.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval The SDRAM memory mode.
+ */
+uint32_t HAL_SDRAM_GetModeStatus(SDRAM_HandleTypeDef *hsdram)
+{
+ /* Return the SDRAM memory current mode */
+ return (FMC_SDRAM_GetModeStatus(hsdram->Instance, hsdram->Init.SDBank));
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SDRAM_Exported_Functions_Group4 State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### SDRAM State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the SDRAM controller
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the SDRAM state.
+ * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains
+ * the configuration information for SDRAM module.
+ * @retval HAL state
+ */
+HAL_SDRAM_StateTypeDef HAL_SDRAM_GetState(const SDRAM_HandleTypeDef *hsdram)
+{
+ return hsdram->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SDRAM_Private_Functions SDRAM Private Functions
+ * @{
+ */
+/**
+ * @brief MDMA SDRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SDRAM_DMACplt(MDMA_HandleTypeDef *hmdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ SDRAM_HandleTypeDef *hsdram = (SDRAM_HandleTypeDef *)(hmdma->Parent);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_READY;
+
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+ hsdram->DmaXferCpltCallback(hmdma);
+#else
+ HAL_SDRAM_DMA_XferCpltCallback(hmdma);
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief MDMA SRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SDRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ SDRAM_HandleTypeDef *hsdram = (SDRAM_HandleTypeDef *)(hmdma->Parent);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_WRITE_PROTECTED;
+
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+ hsdram->DmaXferCpltCallback(hmdma);
+#else
+ HAL_SDRAM_DMA_XferCpltCallback(hmdma);
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief MDMA SDRAM error callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SDRAM_DMAError(MDMA_HandleTypeDef *hmdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ SDRAM_HandleTypeDef *hsdram = (SDRAM_HandleTypeDef *)(hmdma->Parent);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Update the SDRAM controller state */
+ hsdram->State = HAL_SDRAM_STATE_ERROR;
+
+#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1)
+ hsdram->DmaXferErrorCallback(hmdma);
+#else
+ HAL_SDRAM_DMA_XferErrorCallback(hmdma);
+#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+
+#endif /* HAL_SDRAM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sram.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sram.c
new file mode 100755
index 0000000..b3ad7f7
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sram.c
@@ -0,0 +1,1118 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_sram.c
+ * @author MCD Application Team
+ * @brief SRAM HAL module driver.
+ * This file provides a generic firmware to drive SRAM memories
+ * mounted as external device.
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a generic layered driver which contains a set of APIs used to
+ control SRAM memories. It uses the FMC layer functions to interface
+ with SRAM devices.
+ The following sequence should be followed to configure the FMC to interface
+ with SRAM/PSRAM memories:
+
+ (#) Declare a SRAM_HandleTypeDef handle structure, for example:
+ SRAM_HandleTypeDef hsram; and:
+
+ (++) Fill the SRAM_HandleTypeDef handle "Init" field with the allowed
+ values of the structure member.
+
+ (++) Fill the SRAM_HandleTypeDef handle "Instance" field with a predefined
+ base register instance for NOR or SRAM device
+
+ (++) Fill the SRAM_HandleTypeDef handle "Extended" field with a predefined
+ base register instance for NOR or SRAM extended mode
+
+ (#) Declare two FMC_NORSRAM_TimingTypeDef structures, for both normal and extended
+ mode timings; for example:
+ FMC_NORSRAM_TimingTypeDef Timing and FMC_NORSRAM_TimingTypeDef ExTiming;
+ and fill its fields with the allowed values of the structure member.
+
+ (#) Initialize the SRAM Controller by calling the function HAL_SRAM_Init(). This function
+ performs the following sequence:
+
+ (##) MSP hardware layer configuration using the function HAL_SRAM_MspInit()
+ (##) Control register configuration using the FMC NORSRAM interface function
+ FMC_NORSRAM_Init()
+ (##) Timing register configuration using the FMC NORSRAM interface function
+ FMC_NORSRAM_Timing_Init()
+ (##) Extended mode Timing register configuration using the FMC NORSRAM interface function
+ FMC_NORSRAM_Extended_Timing_Init()
+ (##) Enable the SRAM device using the macro __FMC_NORSRAM_ENABLE()
+
+ (#) At this stage you can perform read/write accesses from/to the memory connected
+ to the NOR/SRAM Bank. You can perform either polling or DMA transfer using the
+ following APIs:
+ (++) HAL_SRAM_Read()/HAL_SRAM_Write() for polling read/write access
+ (++) HAL_SRAM_Read_DMA()/HAL_SRAM_Write_DMA() for DMA read/write transfer
+
+ (#) You can also control the SRAM device by calling the control APIs HAL_SRAM_WriteOperation_Enable()/
+ HAL_SRAM_WriteOperation_Disable() to respectively enable/disable the SRAM write operation
+
+ (#) You can continuously monitor the SRAM device HAL state by calling the function
+ HAL_SRAM_GetState()
+
+ *** Callback registration ***
+ =============================================
+ [..]
+ The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ Use Functions HAL_SRAM_RegisterCallback() to register a user callback,
+ it allows to register following callbacks:
+ (+) MspInitCallback : SRAM MspInit.
+ (+) MspDeInitCallback : SRAM MspDeInit.
+ This function takes as parameters the HAL peripheral handle, the Callback ID
+ and a pointer to the user callback function.
+
+ Use function HAL_SRAM_UnRegisterCallback() to reset a callback to the default
+ weak (overridden) function. It allows to reset following callbacks:
+ (+) MspInitCallback : SRAM MspInit.
+ (+) MspDeInitCallback : SRAM MspDeInit.
+ This function) takes as parameters the HAL peripheral handle and the Callback ID.
+
+ By default, after the HAL_SRAM_Init and if the state is HAL_SRAM_STATE_RESET
+ all callbacks are reset to the corresponding legacy weak (overridden) functions.
+ Exception done for MspInit and MspDeInit callbacks that are respectively
+ reset to the legacy weak (overridden) functions in the HAL_SRAM_Init
+ and HAL_SRAM_DeInit only when these callbacks are null (not registered beforehand).
+ If not, MspInit or MspDeInit are not null, the HAL_SRAM_Init and HAL_SRAM_DeInit
+ keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
+
+ Callbacks can be registered/unregistered in READY state only.
+ Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
+ in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
+ during the Init/DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_SRAM_RegisterCallback before calling HAL_SRAM_DeInit
+ or HAL_SRAM_Init function.
+
+ When The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registering feature is not available
+ and weak (overridden) callbacks are used.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+#ifdef HAL_SRAM_MODULE_ENABLED
+
+/** @defgroup SRAM SRAM
+ * @brief SRAM driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup SRAM_Private_Functions SRAM Private Functions
+ * @{
+ */
+static void SRAM_DMACplt(MDMA_HandleTypeDef *hmdma);
+static void SRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma);
+static void SRAM_DMAError(MDMA_HandleTypeDef *hmdma);
+/**
+ * @}
+ */
+
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup SRAM_Exported_Functions SRAM Exported Functions
+ * @{
+ */
+
+/** @defgroup SRAM_Exported_Functions_Group1 Initialization and de-initialization functions
+ * @brief Initialization and Configuration functions.
+ *
+ @verbatim
+ ==============================================================================
+ ##### SRAM Initialization and de_initialization functions #####
+ ==============================================================================
+ [..] This section provides functions allowing to initialize/de-initialize
+ the SRAM memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Performs the SRAM device initialization sequence
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param Timing Pointer to SRAM control timing structure
+ * @param ExtTiming Pointer to SRAM extended mode timing structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram, FMC_NORSRAM_TimingTypeDef *Timing,
+ FMC_NORSRAM_TimingTypeDef *ExtTiming)
+{
+ /* Check the SRAM handle parameter */
+ if (hsram == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (hsram->State == HAL_SRAM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ hsram->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+ if (hsram->MspInitCallback == NULL)
+ {
+ hsram->MspInitCallback = HAL_SRAM_MspInit;
+ }
+ hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback;
+ hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback;
+
+ /* Init the low level hardware */
+ hsram->MspInitCallback(hsram);
+#else
+ /* Initialize the low level hardware (MSP) */
+ HAL_SRAM_MspInit(hsram);
+#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
+ }
+
+ /* Initialize SRAM control Interface */
+ (void)FMC_NORSRAM_Init(hsram->Instance, &(hsram->Init));
+
+ /* Initialize SRAM timing Interface */
+ (void)FMC_NORSRAM_Timing_Init(hsram->Instance, Timing, hsram->Init.NSBank);
+
+ /* Initialize SRAM extended mode timing Interface */
+ (void)FMC_NORSRAM_Extended_Timing_Init(hsram->Extended, ExtTiming, hsram->Init.NSBank,
+ hsram->Init.ExtendedMode);
+
+ /* Enable the NORSRAM device */
+ __FMC_NORSRAM_ENABLE(hsram->Instance, hsram->Init.NSBank);
+
+ /* Enable FMC Peripheral */
+ __FMC_ENABLE();
+
+ /* Initialize the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Performs the SRAM device De-initialization sequence.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_DeInit(SRAM_HandleTypeDef *hsram)
+{
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+ if (hsram->MspDeInitCallback == NULL)
+ {
+ hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
+ }
+
+ /* DeInit the low level hardware */
+ hsram->MspDeInitCallback(hsram);
+#else
+ /* De-Initialize the low level hardware (MSP) */
+ HAL_SRAM_MspDeInit(hsram);
+#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
+
+ /* Configure the SRAM registers with their reset values */
+ (void)FMC_NORSRAM_DeInit(hsram->Instance, hsram->Extended, hsram->Init.NSBank);
+
+ /* Reset the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsram);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief SRAM MSP Init.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval None
+ */
+__weak void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsram);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SRAM_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief SRAM MSP DeInit.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval None
+ */
+__weak void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef *hsram)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hsram);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SRAM_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA transfer complete callback.
+ * @param hmdma pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval None
+ */
+__weak void HAL_SRAM_DMA_XferCpltCallback(MDMA_HandleTypeDef *hmdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdma);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SRAM_DMA_XferCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DMA transfer complete error callback.
+ * @param hmdma pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval None
+ */
+__weak void HAL_SRAM_DMA_XferErrorCallback(MDMA_HandleTypeDef *hmdma)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(hmdma);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_SRAM_DMA_XferErrorCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SRAM_Exported_Functions_Group2 Input Output and memory control functions
+ * @brief Input Output and memory control functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### SRAM Input and Output functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to use and control the SRAM memory
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Reads 8-bit buffer from SRAM memory.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Read_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint8_t *psramaddress = (uint8_t *)pAddress;
+ uint8_t *pdestbuff = pDstBuffer;
+ HAL_SRAM_StateTypeDef state = hsram->State;
+
+ /* Check the SRAM controller state */
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Read data from memory */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *pdestbuff = *psramaddress;
+ pdestbuff++;
+ psramaddress++;
+ }
+
+ /* Update the SRAM controller state */
+ hsram->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Writes 8-bit buffer to SRAM memory.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Write_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint8_t *psramaddress = (uint8_t *)pAddress;
+ uint8_t *psrcbuff = pSrcBuffer;
+
+ /* Check the SRAM controller state */
+ if (hsram->State == HAL_SRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Write data to memory */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *psramaddress = *psrcbuff;
+ psrcbuff++;
+ psramaddress++;
+ }
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads 16-bit buffer from SRAM memory.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Read_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *psramaddress = pAddress;
+ uint16_t *pdestbuff = pDstBuffer;
+ uint8_t limit;
+ HAL_SRAM_StateTypeDef state = hsram->State;
+
+ /* Check the SRAM controller state */
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Check if the size is a 32-bits multiple */
+ limit = (((BufferSize % 2U) != 0U) ? 1U : 0U);
+
+ /* Read data from memory */
+ for (size = BufferSize; size != limit; size -= 2U)
+ {
+ *pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU);
+ pdestbuff++;
+ *pdestbuff = (uint16_t)(((*psramaddress) & 0xFFFF0000U) >> 16U);
+ pdestbuff++;
+ psramaddress++;
+ }
+
+ /* Read last 16-bits if size is not 32-bits multiple */
+ if (limit != 0U)
+ {
+ *pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU);
+ }
+
+ /* Update the SRAM controller state */
+ hsram->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Writes 16-bit buffer to SRAM memory.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Write_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *psramaddress = pAddress;
+ uint16_t *psrcbuff = pSrcBuffer;
+ uint8_t limit;
+
+ /* Check the SRAM controller state */
+ if (hsram->State == HAL_SRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Check if the size is a 32-bits multiple */
+ limit = (((BufferSize % 2U) != 0U) ? 1U : 0U);
+
+ /* Write data to memory */
+ for (size = BufferSize; size != limit; size -= 2U)
+ {
+ *psramaddress = (uint32_t)(*psrcbuff);
+ psrcbuff++;
+ *psramaddress |= ((uint32_t)(*psrcbuff) << 16U);
+ psrcbuff++;
+ psramaddress++;
+ }
+
+ /* Write last 16-bits if size is not 32-bits multiple */
+ if (limit != 0U)
+ {
+ *psramaddress = ((uint32_t)(*psrcbuff) & 0x0000FFFFU) | ((*psramaddress) & 0xFFFF0000U);
+ }
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads 32-bit buffer from SRAM memory.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *psramaddress = pAddress;
+ uint32_t *pdestbuff = pDstBuffer;
+ HAL_SRAM_StateTypeDef state = hsram->State;
+
+ /* Check the SRAM controller state */
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Read data from memory */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *pdestbuff = *psramaddress;
+ pdestbuff++;
+ psramaddress++;
+ }
+
+ /* Update the SRAM controller state */
+ hsram->State = state;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Writes 32-bit buffer to SRAM memory.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Write_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ uint32_t size;
+ __IO uint32_t *psramaddress = pAddress;
+ uint32_t *psrcbuff = pSrcBuffer;
+
+ /* Check the SRAM controller state */
+ if (hsram->State == HAL_SRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Write data to memory */
+ for (size = BufferSize; size != 0U; size--)
+ {
+ *psramaddress = *psrcbuff;
+ psrcbuff++;
+ psramaddress++;
+ }
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Reads a Words data from the SRAM memory using DMA transfer.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to read start address
+ * @param pDstBuffer Pointer to destination buffer
+ * @param BufferSize Size of the buffer to read from memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Read_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer,
+ uint32_t BufferSize)
+{
+ HAL_StatusTypeDef status;
+ HAL_SRAM_StateTypeDef state = hsram->State;
+
+ /* Check the SRAM controller state */
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Configure DMA user callbacks */
+ if (state == HAL_SRAM_STATE_READY)
+ {
+ hsram->hmdma->XferCpltCallback = SRAM_DMACplt;
+ }
+ else
+ {
+ hsram->hmdma->XferCpltCallback = SRAM_DMACpltProt;
+ }
+ hsram->hmdma->XferErrorCallback = SRAM_DMAError;
+
+ /* Enable the DMA Stream */
+ status = HAL_MDMA_Start_IT(hsram->hmdma, (uint32_t)pAddress, (uint32_t)pDstBuffer, (uint32_t)(BufferSize * 4U), 1);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Writes a Words data buffer to SRAM memory using DMA transfer.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @param pAddress Pointer to write start address
+ * @param pSrcBuffer Pointer to source buffer to write
+ * @param BufferSize Size of the buffer to write to memory
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_Write_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer,
+ uint32_t BufferSize)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check the SRAM controller state */
+ if (hsram->State == HAL_SRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Configure DMA user callbacks */
+ hsram->hmdma->XferCpltCallback = SRAM_DMACplt;
+ hsram->hmdma->XferErrorCallback = SRAM_DMAError;
+
+ /* Enable the DMA Stream */
+ status = HAL_MDMA_Start_IT(hsram->hmdma, (uint32_t)pSrcBuffer, (uint32_t)pAddress, (uint32_t)(BufferSize * 4U), 1);
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User SRAM Callback
+ * To be used to override the weak predefined callback
+ * @param hsram : SRAM handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID
+ * @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SRAM_RegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId,
+ pSRAM_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SRAM_StateTypeDef state;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ state = hsram->State;
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_RESET) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_SRAM_MSP_INIT_CB_ID :
+ hsram->MspInitCallback = pCallback;
+ break;
+ case HAL_SRAM_MSP_DEINIT_CB_ID :
+ hsram->MspDeInitCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a User SRAM Callback
+ * SRAM Callback is redirected to the weak predefined callback
+ * @param hsram : SRAM handle
+ * @param CallbackId : ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID
+ * @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID
+ * @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID
+ * @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SRAM_UnRegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SRAM_StateTypeDef state;
+
+ state = hsram->State;
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_SRAM_MSP_INIT_CB_ID :
+ hsram->MspInitCallback = HAL_SRAM_MspInit;
+ break;
+ case HAL_SRAM_MSP_DEINIT_CB_ID :
+ hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
+ break;
+ case HAL_SRAM_DMA_XFER_CPLT_CB_ID :
+ hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback;
+ break;
+ case HAL_SRAM_DMA_XFER_ERR_CB_ID :
+ hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (state == HAL_SRAM_STATE_RESET)
+ {
+ switch (CallbackId)
+ {
+ case HAL_SRAM_MSP_INIT_CB_ID :
+ hsram->MspInitCallback = HAL_SRAM_MspInit;
+ break;
+ case HAL_SRAM_MSP_DEINIT_CB_ID :
+ hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Register a User SRAM Callback for DMA transfers
+ * To be used to override the weak predefined callback
+ * @param hsram : SRAM handle
+ * @param CallbackId : ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID
+ * @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID
+ * @param pCallback : pointer to the Callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_SRAM_RegisterDmaCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId,
+ pSRAM_DmaCallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ HAL_SRAM_StateTypeDef state;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Process locked */
+ __HAL_LOCK(hsram);
+
+ state = hsram->State;
+ if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
+ {
+ switch (CallbackId)
+ {
+ case HAL_SRAM_DMA_XFER_CPLT_CB_ID :
+ hsram->DmaXferCpltCallback = pCallback;
+ break;
+ case HAL_SRAM_DMA_XFER_ERR_CB_ID :
+ hsram->DmaXferErrorCallback = pCallback;
+ break;
+ default :
+ /* update return status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* update return status */
+ status = HAL_ERROR;
+ }
+
+ /* Release Lock */
+ __HAL_UNLOCK(hsram);
+ return status;
+}
+#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup SRAM_Exported_Functions_Group3 Control functions
+ * @brief Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### SRAM Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the SRAM interface.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables dynamically SRAM write operation.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_WriteOperation_Enable(SRAM_HandleTypeDef *hsram)
+{
+ /* Check the SRAM controller state */
+ if (hsram->State == HAL_SRAM_STATE_PROTECTED)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Enable write operation */
+ (void)FMC_NORSRAM_WriteOperation_Enable(hsram->Instance, hsram->Init.NSBank);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_READY;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically SRAM write operation.
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_SRAM_WriteOperation_Disable(SRAM_HandleTypeDef *hsram)
+{
+ /* Check the SRAM controller state */
+ if (hsram->State == HAL_SRAM_STATE_READY)
+ {
+ /* Process Locked */
+ __HAL_LOCK(hsram);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_BUSY;
+
+ /* Disable write operation */
+ (void)FMC_NORSRAM_WriteOperation_Disable(hsram->Instance, hsram->Init.NSBank);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_PROTECTED;
+
+ /* Process unlocked */
+ __HAL_UNLOCK(hsram);
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup SRAM_Exported_Functions_Group4 Peripheral State functions
+ * @brief Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### SRAM State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the SRAM controller
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Returns the SRAM controller state
+ * @param hsram pointer to a SRAM_HandleTypeDef structure that contains
+ * the configuration information for SRAM module.
+ * @retval HAL state
+ */
+HAL_SRAM_StateTypeDef HAL_SRAM_GetState(const SRAM_HandleTypeDef *hsram)
+{
+ return hsram->State;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup SRAM_Private_Functions SRAM Private Functions
+ * @{
+ */
+
+/**
+ * @brief MDMA SRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SRAM_DMACplt(MDMA_HandleTypeDef *hmdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hmdma->Parent);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_READY;
+
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+ hsram->DmaXferCpltCallback(hmdma);
+#else
+ HAL_SRAM_DMA_XferCpltCallback(hmdma);
+#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief MDMA SRAM process complete callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SRAM_DMACpltProt(MDMA_HandleTypeDef *hmdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hmdma->Parent);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_PROTECTED;
+
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+ hsram->DmaXferCpltCallback(hmdma);
+#else
+ HAL_SRAM_DMA_XferCpltCallback(hmdma);
+#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief MDMA SRAM error callback.
+ * @param hmdma : MDMA handle
+ * @retval None
+ */
+static void SRAM_DMAError(MDMA_HandleTypeDef *hmdma)
+{
+ /* Derogation MISRAC2012-Rule-11.5 */
+ SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hmdma->Parent);
+
+ /* Disable the MDMA channel */
+ __HAL_MDMA_DISABLE(hmdma);
+
+ /* Update the SRAM controller state */
+ hsram->State = HAL_SRAM_STATE_ERROR;
+
+#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
+ hsram->DmaXferErrorCallback(hmdma);
+#else
+ HAL_SRAM_DMA_XferErrorCallback(hmdma);
+#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_SRAM_MODULE_ENABLED */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
new file mode 100755
index 0000000..aa6d74c
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim.c
@@ -0,0 +1,7973 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_tim.c
+ * @author MCD Application Team
+ * @brief TIM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Timer (TIM) peripheral:
+ * + TIM Time Base Initialization
+ * + TIM Time Base Start
+ * + TIM Time Base Start Interruption
+ * + TIM Time Base Start DMA
+ * + TIM Output Compare/PWM Initialization
+ * + TIM Output Compare/PWM Channel Configuration
+ * + TIM Output Compare/PWM Start
+ * + TIM Output Compare/PWM Start Interruption
+ * + TIM Output Compare/PWM Start DMA
+ * + TIM Input Capture Initialization
+ * + TIM Input Capture Channel Configuration
+ * + TIM Input Capture Start
+ * + TIM Input Capture Start Interruption
+ * + TIM Input Capture Start DMA
+ * + TIM One Pulse Initialization
+ * + TIM One Pulse Channel Configuration
+ * + TIM One Pulse Start
+ * + TIM Encoder Interface Initialization
+ * + TIM Encoder Interface Start
+ * + TIM Encoder Interface Start Interruption
+ * + TIM Encoder Interface Start DMA
+ * + Commutation Event configuration with Interruption and DMA
+ * + TIM OCRef clear configuration
+ * + TIM External Clock configuration
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### TIMER Generic features #####
+ ==============================================================================
+ [..] The Timer features include:
+ (#) 16-bit up, down, up/down auto-reload counter.
+ (#) 16-bit programmable prescaler allowing dividing (also on the fly) the
+ counter clock frequency either by any factor between 1 and 65536.
+ (#) Up to 4 independent channels for:
+ (++) Input Capture
+ (++) Output Compare
+ (++) PWM generation (Edge and Center-aligned Mode)
+ (++) One-pulse mode output
+ (#) Synchronization circuit to control the timer with external signals and to interconnect
+ several timers together.
+ (#) Supports incremental encoder for positioning purposes
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Initialize the TIM low level resources by implementing the following functions
+ depending on the selected feature:
+ (++) Time Base : HAL_TIM_Base_MspInit()
+ (++) Input Capture : HAL_TIM_IC_MspInit()
+ (++) Output Compare : HAL_TIM_OC_MspInit()
+ (++) PWM generation : HAL_TIM_PWM_MspInit()
+ (++) One-pulse mode output : HAL_TIM_OnePulse_MspInit()
+ (++) Encoder mode output : HAL_TIM_Encoder_MspInit()
+
+ (#) Initialize the TIM low level resources :
+ (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
+ (##) TIM pins configuration
+ (+++) Enable the clock for the TIM GPIOs using the following function:
+ __HAL_RCC_GPIOx_CLK_ENABLE();
+ (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
+
+ (#) The external Clock can be configured, if needed (the default clock is the
+ internal clock from the APBx), using the following function:
+ HAL_TIM_ConfigClockSource, the clock configuration should be done before
+ any start function.
+
+ (#) Configure the TIM in the desired functioning mode using one of the
+ Initialization function of this driver:
+ (++) HAL_TIM_Base_Init: to use the Timer to generate a simple time base
+ (++) HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer to generate an
+ Output Compare signal.
+ (++) HAL_TIM_PWM_Init and HAL_TIM_PWM_ConfigChannel: to use the Timer to generate a
+ PWM signal.
+ (++) HAL_TIM_IC_Init and HAL_TIM_IC_ConfigChannel: to use the Timer to measure an
+ external signal.
+ (++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer
+ in One Pulse Mode.
+ (++) HAL_TIM_Encoder_Init: to use the Timer Encoder Interface.
+
+ (#) Activate the TIM peripheral using one of the start functions depending from the feature used:
+ (++) Time Base : HAL_TIM_Base_Start(), HAL_TIM_Base_Start_DMA(), HAL_TIM_Base_Start_IT()
+ (++) Input Capture : HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(), HAL_TIM_IC_Start_IT()
+ (++) Output Compare : HAL_TIM_OC_Start(), HAL_TIM_OC_Start_DMA(), HAL_TIM_OC_Start_IT()
+ (++) PWM generation : HAL_TIM_PWM_Start(), HAL_TIM_PWM_Start_DMA(), HAL_TIM_PWM_Start_IT()
+ (++) One-pulse mode output : HAL_TIM_OnePulse_Start(), HAL_TIM_OnePulse_Start_IT()
+ (++) Encoder mode output : HAL_TIM_Encoder_Start(), HAL_TIM_Encoder_Start_DMA(), HAL_TIM_Encoder_Start_IT().
+
+ (#) The DMA Burst is managed with the two following functions:
+ HAL_TIM_DMABurst_WriteStart()
+ HAL_TIM_DMABurst_ReadStart()
+
+ *** Callback registration ***
+ =============================================
+
+ [..]
+ The compilation define USE_HAL_TIM_REGISTER_CALLBACKS when set to 1
+ allows the user to configure dynamically the driver callbacks.
+
+ [..]
+ Use Function HAL_TIM_RegisterCallback() to register a callback.
+ HAL_TIM_RegisterCallback() takes as parameters the HAL peripheral handle,
+ the Callback ID and a pointer to the user callback function.
+
+ [..]
+ Use function HAL_TIM_UnRegisterCallback() to reset a callback to the default
+ weak function.
+ HAL_TIM_UnRegisterCallback takes as parameters the HAL peripheral handle,
+ and the Callback ID.
+
+ [..]
+ These functions allow to register/unregister following callbacks:
+ (+) Base_MspInitCallback : TIM Base Msp Init Callback.
+ (+) Base_MspDeInitCallback : TIM Base Msp DeInit Callback.
+ (+) IC_MspInitCallback : TIM IC Msp Init Callback.
+ (+) IC_MspDeInitCallback : TIM IC Msp DeInit Callback.
+ (+) OC_MspInitCallback : TIM OC Msp Init Callback.
+ (+) OC_MspDeInitCallback : TIM OC Msp DeInit Callback.
+ (+) PWM_MspInitCallback : TIM PWM Msp Init Callback.
+ (+) PWM_MspDeInitCallback : TIM PWM Msp DeInit Callback.
+ (+) OnePulse_MspInitCallback : TIM One Pulse Msp Init Callback.
+ (+) OnePulse_MspDeInitCallback : TIM One Pulse Msp DeInit Callback.
+ (+) Encoder_MspInitCallback : TIM Encoder Msp Init Callback.
+ (+) Encoder_MspDeInitCallback : TIM Encoder Msp DeInit Callback.
+ (+) HallSensor_MspInitCallback : TIM Hall Sensor Msp Init Callback.
+ (+) HallSensor_MspDeInitCallback : TIM Hall Sensor Msp DeInit Callback.
+ (+) PeriodElapsedCallback : TIM Period Elapsed Callback.
+ (+) PeriodElapsedHalfCpltCallback : TIM Period Elapsed half complete Callback.
+ (+) TriggerCallback : TIM Trigger Callback.
+ (+) TriggerHalfCpltCallback : TIM Trigger half complete Callback.
+ (+) IC_CaptureCallback : TIM Input Capture Callback.
+ (+) IC_CaptureHalfCpltCallback : TIM Input Capture half complete Callback.
+ (+) OC_DelayElapsedCallback : TIM Output Compare Delay Elapsed Callback.
+ (+) PWM_PulseFinishedCallback : TIM PWM Pulse Finished Callback.
+ (+) PWM_PulseFinishedHalfCpltCallback : TIM PWM Pulse Finished half complete Callback.
+ (+) ErrorCallback : TIM Error Callback.
+ (+) CommutationCallback : TIM Commutation Callback.
+ (+) CommutationHalfCpltCallback : TIM Commutation half complete Callback.
+ (+) BreakCallback : TIM Break Callback.
+ (+) Break2Callback : TIM Break2 Callback.
+
+ [..]
+By default, after the Init and when the state is HAL_TIM_STATE_RESET
+all interrupt callbacks are set to the corresponding weak functions:
+ examples HAL_TIM_TriggerCallback(), HAL_TIM_ErrorCallback().
+
+ [..]
+ Exception done for MspInit and MspDeInit functions that are reset to the legacy weak
+ functionalities in the Init / DeInit only when these callbacks are null
+ (not registered beforehand). If not, MspInit or MspDeInit are not null, the Init / DeInit
+ keep and use the user MspInit / MspDeInit callbacks(registered beforehand)
+
+ [..]
+ Callbacks can be registered / unregistered in HAL_TIM_STATE_READY state only.
+ Exception done MspInit / MspDeInit that can be registered / unregistered
+ in HAL_TIM_STATE_READY or HAL_TIM_STATE_RESET state,
+ thus registered(user) MspInit / DeInit callbacks can be used during the Init / DeInit.
+ In that case first register the MspInit/MspDeInit user callbacks
+ using HAL_TIM_RegisterCallback() before calling DeInit or Init function.
+
+ [..]
+ When The compilation define USE_HAL_TIM_REGISTER_CALLBACKS is set to 0 or
+ not defined, the callback registration feature is not available and all callbacks
+ are set to the corresponding weak functions.
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup TIM TIM
+ * @brief TIM HAL module driver
+ * @{
+ */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/** @addtogroup TIM_Private_Functions
+ * @{
+ */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config);
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter);
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter);
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter);
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter);
+static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint32_t InputTriggerSource);
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMAPeriodElapsedHalfCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma);
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+ const TIM_SlaveConfigTypeDef *sSlaveConfig);
+/**
+ * @}
+ */
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup TIM_Exported_Functions TIM Exported Functions
+ * @{
+ */
+
+/** @defgroup TIM_Exported_Functions_Group1 TIM Time Base functions
+ * @brief Time Base functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Time Base functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM base.
+ (+) De-initialize the TIM base.
+ (+) Start the Time Base.
+ (+) Stop the Time Base.
+ (+) Start the Time Base and enable interrupt.
+ (+) Stop the Time Base and disable interrupt.
+ (+) Start the Time Base and enable DMA transfer.
+ (+) Stop the Time Base and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Time base Unit according to the specified
+ * parameters in the TIM_HandleTypeDef and initialize the associated handle.
+ * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+ * requires a timer reset to avoid unexpected direction
+ * due to DIR bit readonly in center aligned mode.
+ * Ex: call @ref HAL_TIM_Base_DeInit() before HAL_TIM_Base_Init()
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
+{
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->Base_MspInitCallback == NULL)
+ {
+ htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->Base_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ HAL_TIM_Base_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Set the Time Base configuration */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Initialize the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the TIM Base peripheral
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->Base_MspDeInitCallback == NULL)
+ {
+ htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->Base_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIM_Base_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Change the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM Base MSP.
+ * @param htim TIM Base handle
+ * @retval None
+ */
+__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_Base_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Base MSP.
+ * @param htim TIM Base handle
+ * @retval None
+ */
+__weak void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_Base_MspDeInit could be implemented in the user file
+ */
+}
+
+
+/**
+ * @brief Starts the TIM Base generation.
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Check the TIM state */
+ if (htim->State != HAL_TIM_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation.
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Base generation in interrupt mode.
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Check the TIM state */
+ if (htim->State != HAL_TIM_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Enable the TIM Update interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation in interrupt mode.
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ /* Disable the TIM Update interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Base generation in DMA mode.
+ * @param htim TIM Base handle
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+ /* Set the TIM state */
+ if (htim->State == HAL_TIM_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->State == HAL_TIM_STATE_READY)
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_BUSY;
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA Period elapsed callbacks */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&htim->Instance->ARR,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+ /* Enable the TIM Update DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Base generation in DMA mode.
+ * @param htim TIM Base handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_INSTANCE(htim->Instance));
+
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_UPDATE);
+
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group2 TIM Output Compare functions
+ * @brief TIM Output Compare functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM Output Compare functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM Output Compare.
+ (+) De-initialize the TIM Output Compare.
+ (+) Start the TIM Output Compare.
+ (+) Stop the TIM Output Compare.
+ (+) Start the TIM Output Compare and enable interrupt.
+ (+) Stop the TIM Output Compare and disable interrupt.
+ (+) Start the TIM Output Compare and enable DMA transfer.
+ (+) Stop the TIM Output Compare and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Output Compare according to the specified
+ * parameters in the TIM_HandleTypeDef and initializes the associated handle.
+ * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+ * requires a timer reset to avoid unexpected direction
+ * due to DIR bit readonly in center aligned mode.
+ * Ex: call @ref HAL_TIM_OC_DeInit() before HAL_TIM_OC_Init()
+ * @param htim TIM Output Compare handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim)
+{
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->OC_MspInitCallback == NULL)
+ {
+ htim->OC_MspInitCallback = HAL_TIM_OC_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->OC_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_OC_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Init the base time for the Output Compare */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Initialize the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the TIM peripheral
+ * @param htim TIM Output Compare handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->OC_MspDeInitCallback == NULL)
+ {
+ htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->OC_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_OC_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Change the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM Output Compare MSP.
+ * @param htim TIM Output Compare handle
+ * @retval None
+ */
+__weak void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_OC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Output Compare MSP.
+ * @param htim TIM Output Compare handle
+ * @retval None
+ */
+__weak void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_OC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Check the TIM channel state */
+ if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in interrupt mode.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Check the TIM channel state */
+ if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in interrupt mode.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in DMA mode.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+ uint16_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Set the TIM channel state */
+ if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in DMA mode.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Output compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group3 TIM PWM functions
+ * @brief TIM PWM functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM PWM functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM PWM.
+ (+) De-initialize the TIM PWM.
+ (+) Start the TIM PWM.
+ (+) Stop the TIM PWM.
+ (+) Start the TIM PWM and enable interrupt.
+ (+) Stop the TIM PWM and disable interrupt.
+ (+) Start the TIM PWM and enable DMA transfer.
+ (+) Stop the TIM PWM and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM PWM Time Base according to the specified
+ * parameters in the TIM_HandleTypeDef and initializes the associated handle.
+ * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+ * requires a timer reset to avoid unexpected direction
+ * due to DIR bit readonly in center aligned mode.
+ * Ex: call @ref HAL_TIM_PWM_DeInit() before HAL_TIM_PWM_Init()
+ * @param htim TIM PWM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim)
+{
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->PWM_MspInitCallback == NULL)
+ {
+ htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->PWM_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_PWM_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Init the base time for the PWM */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Initialize the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the TIM peripheral
+ * @param htim TIM PWM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->PWM_MspDeInitCallback == NULL)
+ {
+ htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->PWM_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_PWM_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Change the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM PWM MSP.
+ * @param htim TIM PWM handle
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_PWM_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM PWM MSP.
+ * @param htim TIM PWM handle
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_PWM_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Starts the PWM signal generation.
+ * @param htim TIM handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Check the TIM channel state */
+ if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the PWM signal generation.
+ * @param htim TIM PWM handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the PWM signal generation in interrupt mode.
+ * @param htim TIM PWM handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Check the TIM channel state */
+ if (TIM_CHANNEL_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the PWM signal generation in interrupt mode.
+ * @param htim TIM PWM handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Starts the TIM PWM signal generation in DMA mode.
+ * @param htim TIM PWM handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+ uint16_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Set the TIM channel state */
+ if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (TIM_CHANNEL_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Output Capture/Compare 3 request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM PWM signal generation in DMA mode.
+ * @param htim TIM PWM handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group4 TIM Input Capture functions
+ * @brief TIM Input Capture functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM Input Capture functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM Input Capture.
+ (+) De-initialize the TIM Input Capture.
+ (+) Start the TIM Input Capture.
+ (+) Stop the TIM Input Capture.
+ (+) Start the TIM Input Capture and enable interrupt.
+ (+) Stop the TIM Input Capture and disable interrupt.
+ (+) Start the TIM Input Capture and enable DMA transfer.
+ (+) Stop the TIM Input Capture and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Input Capture Time base according to the specified
+ * parameters in the TIM_HandleTypeDef and initializes the associated handle.
+ * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+ * requires a timer reset to avoid unexpected direction
+ * due to DIR bit readonly in center aligned mode.
+ * Ex: call @ref HAL_TIM_IC_DeInit() before HAL_TIM_IC_Init()
+ * @param htim TIM Input Capture handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim)
+{
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->IC_MspInitCallback == NULL)
+ {
+ htim->IC_MspInitCallback = HAL_TIM_IC_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->IC_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_IC_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Init the base time for the input capture */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Initialize the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the TIM peripheral
+ * @param htim TIM Input Capture handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->IC_MspDeInitCallback == NULL)
+ {
+ htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->IC_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_IC_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Change the TIM channels state */
+ TIM_CHANNEL_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET_ALL(htim, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM Input Capture MSP.
+ * @param htim TIM Input Capture handle
+ * @retval None
+ */
+__weak void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_IC_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Input Capture MSP.
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_IC_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Starts the TIM Input Capture measurement.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpsmcr;
+ HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Check the TIM channel state */
+ if ((channel_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Input Capture measurement in interrupt mode.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ /* Check the TIM channel state */
+ if ((channel_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Enable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement in interrupt mode.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Starts the TIM Input Capture measurement in DMA mode.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @param pData The destination Buffer address.
+ * @param Length The length of data to be transferred from TIM peripheral to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ HAL_TIM_ChannelStateTypeDef channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_state = TIM_CHANNEL_N_STATE_GET(htim, Channel);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ /* Set the TIM channel state */
+ if ((channel_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (complementary_channel_state == HAL_TIM_CHANNEL_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if ((channel_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (complementary_channel_state == HAL_TIM_CHANNEL_STATE_READY))
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->CCR3, (uint32_t)pData,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->CCR4, (uint32_t)pData,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM Input Capture measurement in DMA mode.
+ * @param htim TIM Input Capture handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_CHANNEL(htim->Instance, Channel));
+ assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channel */
+ TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Disable the TIM Capture/Compare 4 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group5 TIM One Pulse functions
+ * @brief TIM One Pulse functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM One Pulse functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM One Pulse.
+ (+) De-initialize the TIM One Pulse.
+ (+) Start the TIM One Pulse.
+ (+) Stop the TIM One Pulse.
+ (+) Start the TIM One Pulse and enable interrupt.
+ (+) Stop the TIM One Pulse and disable interrupt.
+ (+) Start the TIM One Pulse and enable DMA transfer.
+ (+) Stop the TIM One Pulse and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM One Pulse Time Base according to the specified
+ * parameters in the TIM_HandleTypeDef and initializes the associated handle.
+ * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+ * requires a timer reset to avoid unexpected direction
+ * due to DIR bit readonly in center aligned mode.
+ * Ex: call @ref HAL_TIM_OnePulse_DeInit() before HAL_TIM_OnePulse_Init()
+ * @note When the timer instance is initialized in One Pulse mode, timer
+ * channels 1 and channel 2 are reserved and cannot be used for other
+ * purpose.
+ * @param htim TIM One Pulse handle
+ * @param OnePulseMode Select the One pulse mode.
+ * This parameter can be one of the following values:
+ * @arg TIM_OPMODE_SINGLE: Only one pulse will be generated.
+ * @arg TIM_OPMODE_REPETITIVE: Repetitive pulses will be generated.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode)
+{
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_OPM_MODE(OnePulseMode));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->OnePulse_MspInitCallback == NULL)
+ {
+ htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->OnePulse_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_OnePulse_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Configure the Time base in the One Pulse Mode */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Reset the OPM Bit */
+ htim->Instance->CR1 &= ~TIM_CR1_OPM;
+
+ /* Configure the OPM Mode */
+ htim->Instance->CR1 |= OnePulseMode;
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Initialize the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the TIM One Pulse
+ * @param htim TIM One Pulse handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->OnePulse_MspDeInitCallback == NULL)
+ {
+ htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->OnePulse_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIM_OnePulse_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM One Pulse MSP.
+ * @param htim TIM One Pulse handle
+ * @retval None
+ */
+__weak void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_OnePulse_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM One Pulse MSP.
+ * @param htim TIM One Pulse handle
+ * @retval None
+ */
+__weak void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_OnePulse_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation.
+ * @note Though OutputChannel parameter is deprecated and ignored by the function
+ * it has been kept to avoid HAL_TIM API compatibility break.
+ * @note The pulse output channel is determined when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel See note above
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Check the TIM channels state */
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+ No need to enable the counter, it's enabled automatically by hardware
+ (the counter starts in response to a stimulus and generate a pulse */
+
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation.
+ * @note Though OutputChannel parameter is deprecated and ignored by the function
+ * it has been kept to avoid HAL_TIM API compatibility break.
+ * @note The pulse output channel is determined when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel See note above
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Disable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation in interrupt mode.
+ * @note Though OutputChannel parameter is deprecated and ignored by the function
+ * it has been kept to avoid HAL_TIM API compatibility break.
+ * @note The pulse output channel is determined when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel See note above
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Check the TIM channels state */
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together
+
+ No need to enable the counter, it's enabled automatically by hardware
+ (the counter starts in response to a stimulus and generate a pulse */
+
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Enable the main output */
+ __HAL_TIM_MOE_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation in interrupt mode.
+ * @note Though OutputChannel parameter is deprecated and ignored by the function
+ * it has been kept to avoid HAL_TIM API compatibility break.
+ * @note The pulse output channel is determined when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel See note above
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(OutputChannel);
+
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+ /* Disable the Capture compare and the Input Capture channels
+ (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2)
+ if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and
+ if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output
+ whatever the combination, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ if (IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
+ {
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group6 TIM Encoder functions
+ * @brief TIM Encoder functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM Encoder functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the TIM Encoder.
+ (+) De-initialize the TIM Encoder.
+ (+) Start the TIM Encoder.
+ (+) Stop the TIM Encoder.
+ (+) Start the TIM Encoder and enable interrupt.
+ (+) Stop the TIM Encoder and disable interrupt.
+ (+) Start the TIM Encoder and enable DMA transfer.
+ (+) Stop the TIM Encoder and disable DMA transfer.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Encoder Interface and initialize the associated handle.
+ * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse)
+ * requires a timer reset to avoid unexpected direction
+ * due to DIR bit readonly in center aligned mode.
+ * Ex: call @ref HAL_TIM_Encoder_DeInit() before HAL_TIM_Encoder_Init()
+ * @note Encoder mode and External clock mode 2 are not compatible and must not be selected together
+ * Ex: A call for @ref HAL_TIM_Encoder_Init will erase the settings of @ref HAL_TIM_ConfigClockSource
+ * using TIM_CLOCKSOURCE_ETRMODE2 and vice versa
+ * @note When the timer instance is initialized in Encoder mode, timer
+ * channels 1 and channel 2 are reserved and cannot be used for other
+ * purpose.
+ * @param htim TIM Encoder Interface handle
+ * @param sConfig TIM Encoder Interface configuration structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, const TIM_Encoder_InitTypeDef *sConfig)
+{
+ uint32_t tmpsmcr;
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+ assert_param(IS_TIM_ENCODER_MODE(sConfig->EncoderMode));
+ assert_param(IS_TIM_IC_SELECTION(sConfig->IC1Selection));
+ assert_param(IS_TIM_IC_SELECTION(sConfig->IC2Selection));
+ assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC1Polarity));
+ assert_param(IS_TIM_ENCODERINPUT_POLARITY(sConfig->IC2Polarity));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->IC2Prescaler));
+ assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+ assert_param(IS_TIM_IC_FILTER(sConfig->IC2Filter));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy weak callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->Encoder_MspInitCallback == NULL)
+ {
+ htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->Encoder_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIM_Encoder_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Reset the SMS and ECE bits */
+ htim->Instance->SMCR &= ~(TIM_SMCR_SMS | TIM_SMCR_ECE);
+
+ /* Configure the Time base in the Encoder Mode */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = htim->Instance->SMCR;
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = htim->Instance->CCMR1;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = htim->Instance->CCER;
+
+ /* Set the encoder Mode */
+ tmpsmcr |= sConfig->EncoderMode;
+
+ /* Select the Capture Compare 1 and the Capture Compare 2 as input */
+ tmpccmr1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S);
+ tmpccmr1 |= (sConfig->IC1Selection | (sConfig->IC2Selection << 8U));
+
+ /* Set the Capture Compare 1 and the Capture Compare 2 prescalers and filters */
+ tmpccmr1 &= ~(TIM_CCMR1_IC1PSC | TIM_CCMR1_IC2PSC);
+ tmpccmr1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_IC2F);
+ tmpccmr1 |= sConfig->IC1Prescaler | (sConfig->IC2Prescaler << 8U);
+ tmpccmr1 |= (sConfig->IC1Filter << 4U) | (sConfig->IC2Filter << 12U);
+
+ /* Set the TI1 and the TI2 Polarities */
+ tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC2P);
+ tmpccer &= ~(TIM_CCER_CC1NP | TIM_CCER_CC2NP);
+ tmpccer |= sConfig->IC1Polarity | (sConfig->IC2Polarity << 4U);
+
+ /* Write to TIMx SMCR */
+ htim->Instance->SMCR = tmpsmcr;
+
+ /* Write to TIMx CCMR1 */
+ htim->Instance->CCMR1 = tmpccmr1;
+
+ /* Write to TIMx CCER */
+ htim->Instance->CCER = tmpccer;
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief DeInitializes the TIM Encoder interface
+ * @param htim TIM Encoder Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->Encoder_MspDeInitCallback == NULL)
+ {
+ htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->Encoder_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIM_Encoder_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM Encoder Interface MSP.
+ * @param htim TIM Encoder Interface handle
+ * @retval None
+ */
+__weak void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_Encoder_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Encoder Interface MSP.
+ * @param htim TIM Encoder Interface handle
+ * @retval None
+ */
+__weak void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_Encoder_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Starts the TIM Encoder Interface.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Set the TIM channel(s) state */
+ if (Channel == TIM_CHANNEL_1)
+ {
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ if ((channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+
+ /* Enable the encoder interface channels */
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ break;
+ }
+
+ default :
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ break;
+ }
+ }
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Encoder Interface.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channels 1 and 2
+ (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+ break;
+ }
+
+ default :
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+ break;
+ }
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel(s) state */
+ if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+ {
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Encoder Interface in interrupt mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Set the TIM channel(s) state */
+ if (Channel == TIM_CHANNEL_1)
+ {
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ if ((channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+
+ /* Enable the encoder interface channels */
+ /* Enable the capture compare Interrupts 1 and/or 2 */
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ default :
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+ }
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Encoder Interface in interrupt mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channels 1 and 2
+ (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+ if (Channel == TIM_CHANNEL_1)
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare Interrupts 1 */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare Interrupts 2 */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ }
+ else
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare Interrupts 1 and 2 */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel(s) state */
+ if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+ {
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Encoder Interface in DMA mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @param pData1 The destination Buffer address for IC1.
+ * @param pData2 The destination Buffer address for IC2.
+ * @param Length The length of data to be transferred from TIM peripheral to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1,
+ uint32_t *pData2, uint16_t Length)
+{
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Set the TIM channel(s) state */
+ if (Channel == TIM_CHANNEL_1)
+ {
+ if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
+ {
+ if ((pData1 == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ if ((channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if ((channel_2_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_READY))
+ {
+ if ((pData2 == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ }
+ else
+ {
+ if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (channel_2_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (complementary_channel_2_state == HAL_TIM_CHANNEL_STATE_READY))
+ {
+ if ((((pData1 == NULL) || (pData2 == NULL))) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError;
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ break;
+ }
+
+ default:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ /* Enable the TIM Input Capture DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+
+ /* Enable the Capture compare channel */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral */
+ __HAL_TIM_ENABLE(htim);
+
+ break;
+ }
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Encoder Interface in DMA mode.
+ * @param htim TIM Encoder Interface handle
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channels 1 and 2
+ (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */
+ if (Channel == TIM_CHANNEL_1)
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare DMA Request 1 */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare DMA Request 2 */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ }
+ else
+ {
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare DMA Request 1 and 2 */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ }
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel(s) state */
+ if ((Channel == TIM_CHANNEL_1) || (Channel == TIM_CHANNEL_2))
+ {
+ TIM_CHANNEL_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management
+ * @brief TIM IRQ handler management
+ *
+@verbatim
+ ==============================================================================
+ ##### IRQ handler management #####
+ ==============================================================================
+ [..]
+ This section provides Timer IRQ handler function.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief This function handles TIM interrupts requests.
+ * @param htim TIM handle
+ * @retval None
+ */
+void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
+{
+ uint32_t itsource = htim->Instance->DIER;
+ uint32_t itflag = htim->Instance->SR;
+
+ /* Capture compare 1 event */
+ if ((itflag & (TIM_FLAG_CC1)) == (TIM_FLAG_CC1))
+ {
+ if ((itsource & (TIM_IT_CC1)) == (TIM_IT_CC1))
+ {
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+ /* Input capture event */
+ if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ }
+ /* Capture compare 2 event */
+ if ((itflag & (TIM_FLAG_CC2)) == (TIM_FLAG_CC2))
+ {
+ if ((itsource & (TIM_IT_CC2)) == (TIM_IT_CC2))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC2);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ /* Input capture event */
+ if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ /* Capture compare 3 event */
+ if ((itflag & (TIM_FLAG_CC3)) == (TIM_FLAG_CC3))
+ {
+ if ((itsource & (TIM_IT_CC3)) == (TIM_IT_CC3))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC3);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ /* Input capture event */
+ if ((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ /* Capture compare 4 event */
+ if ((itflag & (TIM_FLAG_CC4)) == (TIM_FLAG_CC4))
+ {
+ if ((itsource & (TIM_IT_CC4)) == (TIM_IT_CC4))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC4);
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ /* Input capture event */
+ if ((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ /* Output compare event */
+ else
+ {
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->OC_DelayElapsedCallback(htim);
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_OC_DelayElapsedCallback(htim);
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+ }
+ }
+ /* TIM Update event */
+ if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
+ {
+ if ((itsource & (TIM_IT_UPDATE)) == (TIM_IT_UPDATE))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PeriodElapsedCallback(htim);
+#else
+ HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM Break input event */
+ if (((itflag & (TIM_FLAG_BREAK)) == (TIM_FLAG_BREAK)) || \
+ ((itflag & (TIM_FLAG_SYSTEM_BREAK)) == (TIM_FLAG_SYSTEM_BREAK)))
+ {
+ if ((itsource & (TIM_IT_BREAK)) == (TIM_IT_BREAK))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_BREAK | TIM_FLAG_SYSTEM_BREAK);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->BreakCallback(htim);
+#else
+ HAL_TIMEx_BreakCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM Break2 input event */
+ if ((itflag & (TIM_FLAG_BREAK2)) == (TIM_FLAG_BREAK2))
+ {
+ if ((itsource & (TIM_IT_BREAK)) == (TIM_IT_BREAK))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_BREAK2);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->Break2Callback(htim);
+#else
+ HAL_TIMEx_Break2Callback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM Trigger detection event */
+ if ((itflag & (TIM_FLAG_TRIGGER)) == (TIM_FLAG_TRIGGER))
+ {
+ if ((itsource & (TIM_IT_TRIGGER)) == (TIM_IT_TRIGGER))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_TRIGGER);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->TriggerCallback(htim);
+#else
+ HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+ /* TIM commutation event */
+ if ((itflag & (TIM_FLAG_COM)) == (TIM_FLAG_COM))
+ {
+ if ((itsource & (TIM_IT_COM)) == (TIM_IT_COM))
+ {
+ __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_COM);
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->CommutationCallback(htim);
+#else
+ HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+ }
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group8 TIM Peripheral Control functions
+ * @brief TIM Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Configure The Input Output channels for OC, PWM, IC or One Pulse mode.
+ (+) Configure External Clock source.
+ (+) Configure Complementary channels, break features and dead time.
+ (+) Configure Master and the Slave synchronization.
+ (+) Configure the DMA Burst Mode.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the TIM Output Compare Channels according to the specified
+ * parameters in the TIM_OC_InitTypeDef.
+ * @param htim TIM Output Compare handle
+ * @param sConfig TIM Output Compare configuration structure
+ * @param Channel TIM Channels to configure
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim,
+ const TIM_OC_InitTypeDef *sConfig,
+ uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CHANNELS(Channel));
+ assert_param(IS_TIM_OC_MODE(sConfig->OCMode));
+ assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 1 in Output Compare */
+ TIM_OC1_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 2 in Output Compare */
+ TIM_OC2_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 3 in Output Compare */
+ TIM_OC3_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 4 in Output Compare */
+ TIM_OC4_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_5:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC5_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 5 in Output Compare */
+ TIM_OC5_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ case TIM_CHANNEL_6:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC6_INSTANCE(htim->Instance));
+
+ /* Configure the TIM Channel 6 in Output Compare */
+ TIM_OC6_SetConfig(htim->Instance, sConfig);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+
+/**
+ * @brief Initializes the TIM Input Capture Channels according to the specified
+ * parameters in the TIM_IC_InitTypeDef.
+ * @param htim TIM IC handle
+ * @param sConfig TIM Input Capture configuration structure
+ * @param Channel TIM Channel to configure
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_IC_POLARITY(sConfig->ICPolarity));
+ assert_param(IS_TIM_IC_SELECTION(sConfig->ICSelection));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->ICPrescaler));
+ assert_param(IS_TIM_IC_FILTER(sConfig->ICFilter));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ if (Channel == TIM_CHANNEL_1)
+ {
+ /* TI1 Configuration */
+ TIM_TI1_SetConfig(htim->Instance,
+ sConfig->ICPolarity,
+ sConfig->ICSelection,
+ sConfig->ICFilter);
+
+ /* Reset the IC1PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+ /* Set the IC1PSC value */
+ htim->Instance->CCMR1 |= sConfig->ICPrescaler;
+ }
+ else if (Channel == TIM_CHANNEL_2)
+ {
+ /* TI2 Configuration */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ TIM_TI2_SetConfig(htim->Instance,
+ sConfig->ICPolarity,
+ sConfig->ICSelection,
+ sConfig->ICFilter);
+
+ /* Reset the IC2PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+ /* Set the IC2PSC value */
+ htim->Instance->CCMR1 |= (sConfig->ICPrescaler << 8U);
+ }
+ else if (Channel == TIM_CHANNEL_3)
+ {
+ /* TI3 Configuration */
+ assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+ TIM_TI3_SetConfig(htim->Instance,
+ sConfig->ICPolarity,
+ sConfig->ICSelection,
+ sConfig->ICFilter);
+
+ /* Reset the IC3PSC Bits */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC;
+
+ /* Set the IC3PSC value */
+ htim->Instance->CCMR2 |= sConfig->ICPrescaler;
+ }
+ else if (Channel == TIM_CHANNEL_4)
+ {
+ /* TI4 Configuration */
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+ TIM_TI4_SetConfig(htim->Instance,
+ sConfig->ICPolarity,
+ sConfig->ICSelection,
+ sConfig->ICFilter);
+
+ /* Reset the IC4PSC Bits */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC;
+
+ /* Set the IC4PSC value */
+ htim->Instance->CCMR2 |= (sConfig->ICPrescaler << 8U);
+ }
+ else
+ {
+ status = HAL_ERROR;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+
+/**
+ * @brief Initializes the TIM PWM channels according to the specified
+ * parameters in the TIM_OC_InitTypeDef.
+ * @param htim TIM PWM handle
+ * @param sConfig TIM PWM configuration structure
+ * @param Channel TIM Channels to be configured
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim,
+ const TIM_OC_InitTypeDef *sConfig,
+ uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CHANNELS(Channel));
+ assert_param(IS_TIM_PWM_MODE(sConfig->OCMode));
+ assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity));
+ assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 1 in PWM mode */
+ TIM_OC1_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel1 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE;
+ htim->Instance->CCMR1 |= sConfig->OCFastMode;
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 2 in PWM mode */
+ TIM_OC2_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel2 */
+ htim->Instance->CCMR1 |= TIM_CCMR1_OC2PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE;
+ htim->Instance->CCMR1 |= sConfig->OCFastMode << 8U;
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 3 in PWM mode */
+ TIM_OC3_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel3 */
+ htim->Instance->CCMR2 |= TIM_CCMR2_OC3PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE;
+ htim->Instance->CCMR2 |= sConfig->OCFastMode;
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 4 in PWM mode */
+ TIM_OC4_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel4 */
+ htim->Instance->CCMR2 |= TIM_CCMR2_OC4PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE;
+ htim->Instance->CCMR2 |= sConfig->OCFastMode << 8U;
+ break;
+ }
+
+ case TIM_CHANNEL_5:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC5_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 5 in PWM mode */
+ TIM_OC5_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel5*/
+ htim->Instance->CCMR3 |= TIM_CCMR3_OC5PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5FE;
+ htim->Instance->CCMR3 |= sConfig->OCFastMode;
+ break;
+ }
+
+ case TIM_CHANNEL_6:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC6_INSTANCE(htim->Instance));
+
+ /* Configure the Channel 6 in PWM mode */
+ TIM_OC6_SetConfig(htim->Instance, sConfig);
+
+ /* Set the Preload enable bit for channel6 */
+ htim->Instance->CCMR3 |= TIM_CCMR3_OC6PE;
+
+ /* Configure the Output Fast mode */
+ htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6FE;
+ htim->Instance->CCMR3 |= sConfig->OCFastMode << 8U;
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+
+/**
+ * @brief Initializes the TIM One Pulse Channels according to the specified
+ * parameters in the TIM_OnePulse_InitTypeDef.
+ * @param htim TIM One Pulse handle
+ * @param sConfig TIM One Pulse configuration structure
+ * @param OutputChannel TIM output channel to configure
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @param InputChannel TIM input Channel to configure
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @note To output a waveform with a minimum delay user can enable the fast
+ * mode by calling the @ref __HAL_TIM_ENABLE_OCxFAST macro. Then CCx
+ * output is forced in response to the edge detection on TIx input,
+ * without taking in account the comparison.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef *sConfig,
+ uint32_t OutputChannel, uint32_t InputChannel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ TIM_OC_InitTypeDef temp1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_OPM_CHANNELS(OutputChannel));
+ assert_param(IS_TIM_OPM_CHANNELS(InputChannel));
+
+ if (OutputChannel != InputChannel)
+ {
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Extract the Output compare configuration from sConfig structure */
+ temp1.OCMode = sConfig->OCMode;
+ temp1.Pulse = sConfig->Pulse;
+ temp1.OCPolarity = sConfig->OCPolarity;
+ temp1.OCNPolarity = sConfig->OCNPolarity;
+ temp1.OCIdleState = sConfig->OCIdleState;
+ temp1.OCNIdleState = sConfig->OCNIdleState;
+
+ switch (OutputChannel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ TIM_OC1_SetConfig(htim->Instance, &temp1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ TIM_OC2_SetConfig(htim->Instance, &temp1);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ switch (InputChannel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ TIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity,
+ sConfig->ICSelection, sConfig->ICFilter);
+
+ /* Reset the IC1PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+
+ /* Select the Trigger source */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= TIM_TS_TI1FP1;
+
+ /* Select the Slave Mode */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+ htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ TIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity,
+ sConfig->ICSelection, sConfig->ICFilter);
+
+ /* Reset the IC2PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC;
+
+ /* Select the Trigger source */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= TIM_TS_TI2FP2;
+
+ /* Select the Slave Mode */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+ htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER;
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+}
+
+/**
+ * @brief Configure the DMA Burst to transfer Data from the memory to the TIM peripheral
+ * @param htim TIM handle
+ * @param BurstBaseAddress TIM Base address from where the DMA will start the Data write
+ * This parameter can be one of the following values:
+ * @arg TIM_DMABASE_CR1
+ * @arg TIM_DMABASE_CR2
+ * @arg TIM_DMABASE_SMCR
+ * @arg TIM_DMABASE_DIER
+ * @arg TIM_DMABASE_SR
+ * @arg TIM_DMABASE_EGR
+ * @arg TIM_DMABASE_CCMR1
+ * @arg TIM_DMABASE_CCMR2
+ * @arg TIM_DMABASE_CCER
+ * @arg TIM_DMABASE_CNT
+ * @arg TIM_DMABASE_PSC
+ * @arg TIM_DMABASE_ARR
+ * @arg TIM_DMABASE_RCR
+ * @arg TIM_DMABASE_CCR1
+ * @arg TIM_DMABASE_CCR2
+ * @arg TIM_DMABASE_CCR3
+ * @arg TIM_DMABASE_CCR4
+ * @arg TIM_DMABASE_BDTR
+ * @arg TIM_DMABASE_CCMR3
+ * @arg TIM_DMABASE_CCR5
+ * @arg TIM_DMABASE_CCR6
+ * @arg TIM_DMABASE_AF1
+ * @arg TIM_DMABASE_AF2
+ * @arg TIM_DMABASE_TISEL
+ *
+ * @param BurstRequestSrc TIM DMA Request sources
+ * This parameter can be one of the following values:
+ * @arg TIM_DMA_UPDATE: TIM update Interrupt source
+ * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+ * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+ * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+ * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+ * @arg TIM_DMA_COM: TIM Commutation DMA source
+ * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+ * @param BurstBuffer The Buffer address.
+ * @param BurstLength DMA Burst length. This parameter can be one value
+ * between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+ * @note This function should be used only when BurstLength is equal to DMA data transfer length.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+ uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+ uint32_t BurstLength)
+{
+ HAL_StatusTypeDef status;
+
+ status = HAL_TIM_DMABurst_MultiWriteStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+ ((BurstLength) >> 8U) + 1U);
+
+
+ return status;
+}
+
+/**
+ * @brief Configure the DMA Burst to transfer multiple Data from the memory to the TIM peripheral
+ * @param htim TIM handle
+ * @param BurstBaseAddress TIM Base address from where the DMA will start the Data write
+ * This parameter can be one of the following values:
+ * @arg TIM_DMABASE_CR1
+ * @arg TIM_DMABASE_CR2
+ * @arg TIM_DMABASE_SMCR
+ * @arg TIM_DMABASE_DIER
+ * @arg TIM_DMABASE_SR
+ * @arg TIM_DMABASE_EGR
+ * @arg TIM_DMABASE_CCMR1
+ * @arg TIM_DMABASE_CCMR2
+ * @arg TIM_DMABASE_CCER
+ * @arg TIM_DMABASE_CNT
+ * @arg TIM_DMABASE_PSC
+ * @arg TIM_DMABASE_ARR
+ * @arg TIM_DMABASE_RCR
+ * @arg TIM_DMABASE_CCR1
+ * @arg TIM_DMABASE_CCR2
+ * @arg TIM_DMABASE_CCR3
+ * @arg TIM_DMABASE_CCR4
+ * @arg TIM_DMABASE_BDTR
+ * @arg TIM_DMABASE_CCMR3
+ * @arg TIM_DMABASE_CCR5
+ * @arg TIM_DMABASE_CCR6
+ * @arg TIM_DMABASE_AF1
+ * @arg TIM_DMABASE_AF2
+ * @arg TIM_DMABASE_TISEL
+ *
+ * @param BurstRequestSrc TIM DMA Request sources
+ * This parameter can be one of the following values:
+ * @arg TIM_DMA_UPDATE: TIM update Interrupt source
+ * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+ * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+ * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+ * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+ * @arg TIM_DMA_COM: TIM Commutation DMA source
+ * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+ * @param BurstBuffer The Buffer address.
+ * @param BurstLength DMA Burst length. This parameter can be one value
+ * between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+ * @param DataLength Data length. This parameter can be one value
+ * between 1 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+ uint32_t BurstRequestSrc, const uint32_t *BurstBuffer,
+ uint32_t BurstLength, uint32_t DataLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_DMA_BASE(BurstBaseAddress));
+ assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+ assert_param(IS_TIM_DMA_LENGTH(BurstLength));
+ assert_param(IS_TIM_DMA_DATA_LENGTH(DataLength));
+
+ if (htim->DMABurstState == HAL_DMA_BURST_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->DMABurstState == HAL_DMA_BURST_STATE_READY)
+ {
+ if ((BurstBuffer == NULL) && (BurstLength > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->DMABurstState = HAL_DMA_BURST_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+ switch (BurstRequestSrc)
+ {
+ case TIM_DMA_UPDATE:
+ {
+ /* Set the DMA Period elapsed callbacks */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC1:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC2:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC3:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC4:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt;
+ htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_COM:
+ {
+ /* Set the DMA commutation callbacks */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_TRIGGER:
+ {
+ /* Set the DMA trigger callbacks */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferHalfCpltCallback = TIM_DMATriggerHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)BurstBuffer,
+ (uint32_t)&htim->Instance->DMAR, DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the DMA Burst Mode */
+ htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+ /* Enable the TIM DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM DMA Burst mode
+ * @param htim TIM handle
+ * @param BurstRequestSrc TIM DMA Request sources to disable
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+
+ /* Abort the DMA transfer (at least disable the DMA stream) */
+ switch (BurstRequestSrc)
+ {
+ case TIM_DMA_UPDATE:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+ break;
+ }
+ case TIM_DMA_CC1:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+ case TIM_DMA_CC2:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+ case TIM_DMA_CC3:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+ case TIM_DMA_CC4:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+ case TIM_DMA_COM:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+ break;
+ }
+ case TIM_DMA_TRIGGER:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Configure the DMA Burst to transfer Data from the TIM peripheral to the memory
+ * @param htim TIM handle
+ * @param BurstBaseAddress TIM Base address from where the DMA will start the Data read
+ * This parameter can be one of the following values:
+ * @arg TIM_DMABASE_CR1
+ * @arg TIM_DMABASE_CR2
+ * @arg TIM_DMABASE_SMCR
+ * @arg TIM_DMABASE_DIER
+ * @arg TIM_DMABASE_SR
+ * @arg TIM_DMABASE_EGR
+ * @arg TIM_DMABASE_CCMR1
+ * @arg TIM_DMABASE_CCMR2
+ * @arg TIM_DMABASE_CCER
+ * @arg TIM_DMABASE_CNT
+ * @arg TIM_DMABASE_PSC
+ * @arg TIM_DMABASE_ARR
+ * @arg TIM_DMABASE_RCR
+ * @arg TIM_DMABASE_CCR1
+ * @arg TIM_DMABASE_CCR2
+ * @arg TIM_DMABASE_CCR3
+ * @arg TIM_DMABASE_CCR4
+ * @arg TIM_DMABASE_BDTR
+ * @arg TIM_DMABASE_CCMR3
+ * @arg TIM_DMABASE_CCR5
+ * @arg TIM_DMABASE_CCR6
+ * @arg TIM_DMABASE_AF1
+ * @arg TIM_DMABASE_AF2
+ * @arg TIM_DMABASE_TISEL
+ *
+ * @param BurstRequestSrc TIM DMA Request sources
+ * This parameter can be one of the following values:
+ * @arg TIM_DMA_UPDATE: TIM update Interrupt source
+ * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+ * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+ * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+ * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+ * @arg TIM_DMA_COM: TIM Commutation DMA source
+ * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+ * @param BurstBuffer The Buffer address.
+ * @param BurstLength DMA Burst length. This parameter can be one value
+ * between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+ * @note This function should be used only when BurstLength is equal to DMA data transfer length.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+ uint32_t BurstRequestSrc, uint32_t *BurstBuffer, uint32_t BurstLength)
+{
+ HAL_StatusTypeDef status;
+
+ status = HAL_TIM_DMABurst_MultiReadStart(htim, BurstBaseAddress, BurstRequestSrc, BurstBuffer, BurstLength,
+ ((BurstLength) >> 8U) + 1U);
+
+
+ return status;
+}
+
+/**
+ * @brief Configure the DMA Burst to transfer Data from the TIM peripheral to the memory
+ * @param htim TIM handle
+ * @param BurstBaseAddress TIM Base address from where the DMA will start the Data read
+ * This parameter can be one of the following values:
+ * @arg TIM_DMABASE_CR1
+ * @arg TIM_DMABASE_CR2
+ * @arg TIM_DMABASE_SMCR
+ * @arg TIM_DMABASE_DIER
+ * @arg TIM_DMABASE_SR
+ * @arg TIM_DMABASE_EGR
+ * @arg TIM_DMABASE_CCMR1
+ * @arg TIM_DMABASE_CCMR2
+ * @arg TIM_DMABASE_CCER
+ * @arg TIM_DMABASE_CNT
+ * @arg TIM_DMABASE_PSC
+ * @arg TIM_DMABASE_ARR
+ * @arg TIM_DMABASE_RCR
+ * @arg TIM_DMABASE_CCR1
+ * @arg TIM_DMABASE_CCR2
+ * @arg TIM_DMABASE_CCR3
+ * @arg TIM_DMABASE_CCR4
+ * @arg TIM_DMABASE_BDTR
+ * @arg TIM_DMABASE_CCMR3
+ * @arg TIM_DMABASE_CCR5
+ * @arg TIM_DMABASE_CCR6
+ * @arg TIM_DMABASE_AF1
+ * @arg TIM_DMABASE_AF2
+ * @arg TIM_DMABASE_TISEL
+ *
+ * @param BurstRequestSrc TIM DMA Request sources
+ * This parameter can be one of the following values:
+ * @arg TIM_DMA_UPDATE: TIM update Interrupt source
+ * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
+ * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
+ * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
+ * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
+ * @arg TIM_DMA_COM: TIM Commutation DMA source
+ * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source
+ * @param BurstBuffer The Buffer address.
+ * @param BurstLength DMA Burst length. This parameter can be one value
+ * between: TIM_DMABURSTLENGTH_1TRANSFER and TIM_DMABURSTLENGTH_18TRANSFERS.
+ * @param DataLength Data length. This parameter can be one value
+ * between 1 and 0xFFFF.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_MultiReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress,
+ uint32_t BurstRequestSrc, uint32_t *BurstBuffer,
+ uint32_t BurstLength, uint32_t DataLength)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_DMA_BASE(BurstBaseAddress));
+ assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+ assert_param(IS_TIM_DMA_LENGTH(BurstLength));
+ assert_param(IS_TIM_DMA_DATA_LENGTH(DataLength));
+
+ if (htim->DMABurstState == HAL_DMA_BURST_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (htim->DMABurstState == HAL_DMA_BURST_STATE_READY)
+ {
+ if ((BurstBuffer == NULL) && (BurstLength > 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ htim->DMABurstState = HAL_DMA_BURST_STATE_BUSY;
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+ switch (BurstRequestSrc)
+ {
+ case TIM_DMA_UPDATE:
+ {
+ /* Set the DMA Period elapsed callbacks */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt;
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferHalfCpltCallback = TIM_DMAPeriodElapsedHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC1:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC2:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC3:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_CC4:
+ {
+ /* Set the DMA capture callbacks */
+ htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC4]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_COM:
+ {
+ /* Set the DMA commutation callbacks */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ case TIM_DMA_TRIGGER:
+ {
+ /* Set the DMA trigger callbacks */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt;
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferHalfCpltCallback = TIM_DMATriggerHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer,
+ DataLength) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Configure the DMA Burst Mode */
+ htim->Instance->DCR = (BurstBaseAddress | BurstLength);
+
+ /* Enable the TIM DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stop the DMA burst reading
+ * @param htim TIM handle
+ * @param BurstRequestSrc TIM DMA Request sources to disable.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc));
+
+ /* Abort the DMA transfer (at least disable the DMA stream) */
+ switch (BurstRequestSrc)
+ {
+ case TIM_DMA_UPDATE:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_UPDATE]);
+ break;
+ }
+ case TIM_DMA_CC1:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+ case TIM_DMA_CC2:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+ case TIM_DMA_CC3:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+ case TIM_DMA_CC4:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC4]);
+ break;
+ }
+ case TIM_DMA_COM:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_COMMUTATION]);
+ break;
+ }
+ case TIM_DMA_TRIGGER:
+ {
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_TRIGGER]);
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the TIM Update DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc);
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Generate a software event
+ * @param htim TIM handle
+ * @param EventSource specifies the event source.
+ * This parameter can be one of the following values:
+ * @arg TIM_EVENTSOURCE_UPDATE: Timer update Event source
+ * @arg TIM_EVENTSOURCE_CC1: Timer Capture Compare 1 Event source
+ * @arg TIM_EVENTSOURCE_CC2: Timer Capture Compare 2 Event source
+ * @arg TIM_EVENTSOURCE_CC3: Timer Capture Compare 3 Event source
+ * @arg TIM_EVENTSOURCE_CC4: Timer Capture Compare 4 Event source
+ * @arg TIM_EVENTSOURCE_COM: Timer COM event source
+ * @arg TIM_EVENTSOURCE_TRIGGER: Timer Trigger Event source
+ * @arg TIM_EVENTSOURCE_BREAK: Timer Break event source
+ * @arg TIM_EVENTSOURCE_BREAK2: Timer Break2 event source
+ * @note Basic timers can only generate an update event.
+ * @note TIM_EVENTSOURCE_COM is relevant only with advanced timer instances.
+ * @note TIM_EVENTSOURCE_BREAK and TIM_EVENTSOURCE_BREAK2 are relevant
+ * only for timer instances supporting break input(s).
+ * @retval HAL status
+ */
+
+HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_EVENT_SOURCE(EventSource));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ /* Change the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Set the event sources */
+ htim->Instance->EGR = EventSource;
+
+ /* Change the TIM state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the OCRef clear feature
+ * @param htim TIM handle
+ * @param sClearInputConfig pointer to a TIM_ClearInputConfigTypeDef structure that
+ * contains the OCREF clear feature and parameters for the TIM peripheral.
+ * @param Channel specifies the TIM Channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1
+ * @arg TIM_CHANNEL_2: TIM Channel 2
+ * @arg TIM_CHANNEL_3: TIM Channel 3
+ * @arg TIM_CHANNEL_4: TIM Channel 4
+ * @arg TIM_CHANNEL_5: TIM Channel 5
+ * @arg TIM_CHANNEL_6: TIM Channel 6
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim,
+ const TIM_ClearInputConfigTypeDef *sClearInputConfig,
+ uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_OCXREF_CLEAR_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ switch (sClearInputConfig->ClearInputSource)
+ {
+ case TIM_CLEARINPUTSOURCE_NONE:
+ {
+ /* Clear the OCREF clear selection bit and the the ETR Bits */
+ CLEAR_BIT(htim->Instance->SMCR, (TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP));
+ break;
+ }
+
+ case TIM_CLEARINPUTSOURCE_ETR:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CLEARINPUT_POLARITY(sClearInputConfig->ClearInputPolarity));
+ assert_param(IS_TIM_CLEARINPUT_PRESCALER(sClearInputConfig->ClearInputPrescaler));
+ assert_param(IS_TIM_CLEARINPUT_FILTER(sClearInputConfig->ClearInputFilter));
+
+ /* When OCRef clear feature is used with ETR source, ETR prescaler must be off */
+ if (sClearInputConfig->ClearInputPrescaler != TIM_CLEARINPUTPRESCALER_DIV1)
+ {
+ htim->State = HAL_TIM_STATE_READY;
+ __HAL_UNLOCK(htim);
+ return HAL_ERROR;
+ }
+
+ TIM_ETR_SetConfig(htim->Instance,
+ sClearInputConfig->ClearInputPrescaler,
+ sClearInputConfig->ClearInputPolarity,
+ sClearInputConfig->ClearInputFilter);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+ {
+ /* Enable the OCREF clear feature for Channel 1 */
+ SET_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC1CE);
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 1 */
+ CLEAR_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC1CE);
+ }
+ break;
+ }
+ case TIM_CHANNEL_2:
+ {
+ if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+ {
+ /* Enable the OCREF clear feature for Channel 2 */
+ SET_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC2CE);
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 2 */
+ CLEAR_BIT(htim->Instance->CCMR1, TIM_CCMR1_OC2CE);
+ }
+ break;
+ }
+ case TIM_CHANNEL_3:
+ {
+ if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+ {
+ /* Enable the OCREF clear feature for Channel 3 */
+ SET_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC3CE);
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 3 */
+ CLEAR_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC3CE);
+ }
+ break;
+ }
+ case TIM_CHANNEL_4:
+ {
+ if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+ {
+ /* Enable the OCREF clear feature for Channel 4 */
+ SET_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC4CE);
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 4 */
+ CLEAR_BIT(htim->Instance->CCMR2, TIM_CCMR2_OC4CE);
+ }
+ break;
+ }
+ case TIM_CHANNEL_5:
+ {
+ if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+ {
+ /* Enable the OCREF clear feature for Channel 5 */
+ SET_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC5CE);
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 5 */
+ CLEAR_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC5CE);
+ }
+ break;
+ }
+ case TIM_CHANNEL_6:
+ {
+ if (sClearInputConfig->ClearInputState != (uint32_t)DISABLE)
+ {
+ /* Enable the OCREF clear feature for Channel 6 */
+ SET_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC6CE);
+ }
+ else
+ {
+ /* Disable the OCREF clear feature for Channel 6 */
+ CLEAR_BIT(htim->Instance->CCMR3, TIM_CCMR3_OC6CE);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+
+/**
+ * @brief Configures the clock source to be used
+ * @param htim TIM handle
+ * @param sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that
+ * contains the clock source information for the TIM peripheral.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CLOCKSOURCE(sClockSourceConfig->ClockSource));
+
+ /* Reset the SMS, TS, ECE, ETPS and ETRF bits */
+ tmpsmcr = htim->Instance->SMCR;
+ tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS);
+ tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+ htim->Instance->SMCR = tmpsmcr;
+
+ switch (sClockSourceConfig->ClockSource)
+ {
+ case TIM_CLOCKSOURCE_INTERNAL:
+ {
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+ break;
+ }
+
+ case TIM_CLOCKSOURCE_ETRMODE1:
+ {
+ /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/
+ assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
+
+ /* Check ETR input conditioning related parameters */
+ assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+ assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+ assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+ /* Configure the ETR Clock source */
+ TIM_ETR_SetConfig(htim->Instance,
+ sClockSourceConfig->ClockPrescaler,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+
+ /* Select the External clock mode1 and the ETRF trigger */
+ tmpsmcr = htim->Instance->SMCR;
+ tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1);
+ /* Write to TIMx SMCR */
+ htim->Instance->SMCR = tmpsmcr;
+ break;
+ }
+
+ case TIM_CLOCKSOURCE_ETRMODE2:
+ {
+ /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/
+ assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance));
+
+ /* Check ETR input conditioning related parameters */
+ assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler));
+ assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+ assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+ /* Configure the ETR Clock source */
+ TIM_ETR_SetConfig(htim->Instance,
+ sClockSourceConfig->ClockPrescaler,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ /* Enable the External clock mode2 */
+ htim->Instance->SMCR |= TIM_SMCR_ECE;
+ break;
+ }
+
+ case TIM_CLOCKSOURCE_TI1:
+ {
+ /* Check whether or not the timer instance supports external clock mode 1 */
+ assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+ /* Check TI1 input conditioning related parameters */
+ assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+ assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+ TIM_TI1_ConfigInputStage(htim->Instance,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1);
+ break;
+ }
+
+ case TIM_CLOCKSOURCE_TI2:
+ {
+ /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/
+ assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+ /* Check TI2 input conditioning related parameters */
+ assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+ assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+ TIM_TI2_ConfigInputStage(htim->Instance,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2);
+ break;
+ }
+
+ case TIM_CLOCKSOURCE_TI1ED:
+ {
+ /* Check whether or not the timer instance supports external clock mode 1 */
+ assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance));
+
+ /* Check TI1 input conditioning related parameters */
+ assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity));
+ assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter));
+
+ TIM_TI1_ConfigInputStage(htim->Instance,
+ sClockSourceConfig->ClockPolarity,
+ sClockSourceConfig->ClockFilter);
+ TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED);
+ break;
+ }
+
+ case TIM_CLOCKSOURCE_ITR0:
+ case TIM_CLOCKSOURCE_ITR1:
+ case TIM_CLOCKSOURCE_ITR2:
+ case TIM_CLOCKSOURCE_ITR3:
+ case TIM_CLOCKSOURCE_ITR4:
+ case TIM_CLOCKSOURCE_ITR5:
+ case TIM_CLOCKSOURCE_ITR6:
+ case TIM_CLOCKSOURCE_ITR7:
+ case TIM_CLOCKSOURCE_ITR8:
+ {
+ /* Check whether or not the timer instance supports internal trigger input */
+ assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance));
+
+ TIM_ITRx_SetConfig(htim->Instance, sClockSourceConfig->ClockSource);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+
+/**
+ * @brief Selects the signal connected to the TI1 input: direct from CH1_input
+ * or a XOR combination between CH1_input, CH2_input & CH3_input
+ * @param htim TIM handle.
+ * @param TI1_Selection Indicate whether or not channel 1 is connected to the
+ * output of a XOR gate.
+ * This parameter can be one of the following values:
+ * @arg TIM_TI1SELECTION_CH1: The TIMx_CH1 pin is connected to TI1 input
+ * @arg TIM_TI1SELECTION_XORCOMBINATION: The TIMx_CH1, CH2 and CH3
+ * pins are connected to the TI1 input (XOR combination)
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection)
+{
+ uint32_t tmpcr2;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_XOR_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TI1SELECTION(TI1_Selection));
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = htim->Instance->CR2;
+
+ /* Reset the TI1 selection */
+ tmpcr2 &= ~TIM_CR2_TI1S;
+
+ /* Set the TI1 selection */
+ tmpcr2 |= TI1_Selection;
+
+ /* Write to TIMxCR2 */
+ htim->Instance->CR2 = tmpcr2;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the TIM in Slave mode
+ * @param htim TIM handle.
+ * @param sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that
+ * contains the selected trigger (internal trigger input, filtered
+ * timer input or external trigger input) and the Slave mode
+ * (Disable, Reset, Gated, Trigger, External clock mode 1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode));
+ assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger));
+
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ if (TIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
+ {
+ htim->State = HAL_TIM_STATE_READY;
+ __HAL_UNLOCK(htim);
+ return HAL_ERROR;
+ }
+
+ /* Disable Trigger Interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_TRIGGER);
+
+ /* Disable Trigger DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER);
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the TIM in Slave mode in interrupt mode
+ * @param htim TIM handle.
+ * @param sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that
+ * contains the selected trigger (internal trigger input, filtered
+ * timer input or external trigger input) and the Slave mode
+ * (Disable, Reset, Gated, Trigger, External clock mode 1).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim,
+ const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode));
+ assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger));
+
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ if (TIM_SlaveTimer_SetConfig(htim, sSlaveConfig) != HAL_OK)
+ {
+ htim->State = HAL_TIM_STATE_READY;
+ __HAL_UNLOCK(htim);
+ return HAL_ERROR;
+ }
+
+ /* Enable Trigger Interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_TRIGGER);
+
+ /* Disable Trigger DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER);
+
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Read the captured value from Capture Compare unit
+ * @param htim TIM handle.
+ * @param Channel TIM Channels to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @retval Captured value
+ */
+uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpreg = 0U;
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+
+ /* Return the capture 1 value */
+ tmpreg = htim->Instance->CCR1;
+
+ break;
+ }
+ case TIM_CHANNEL_2:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+
+ /* Return the capture 2 value */
+ tmpreg = htim->Instance->CCR2;
+
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC3_INSTANCE(htim->Instance));
+
+ /* Return the capture 3 value */
+ tmpreg = htim->Instance->CCR3;
+
+ break;
+ }
+
+ case TIM_CHANNEL_4:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC4_INSTANCE(htim->Instance));
+
+ /* Return the capture 4 value */
+ tmpreg = htim->Instance->CCR4;
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return tmpreg;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions
+ * @brief TIM Callbacks functions
+ *
+@verbatim
+ ==============================================================================
+ ##### TIM Callbacks functions #####
+ ==============================================================================
+ [..]
+ This section provides TIM callback functions:
+ (+) TIM Period elapsed callback
+ (+) TIM Output Compare callback
+ (+) TIM Input capture callback
+ (+) TIM Trigger callback
+ (+) TIM Error callback
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Period elapsed callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Period elapsed half complete callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_PeriodElapsedHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_PeriodElapsedHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Output Compare callback in non-blocking mode
+ * @param htim TIM OC handle
+ * @retval None
+ */
+__weak void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_OC_DelayElapsedCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Input Capture callback in non-blocking mode
+ * @param htim TIM IC handle
+ * @retval None
+ */
+__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_IC_CaptureCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Input Capture half complete callback in non-blocking mode
+ * @param htim TIM IC handle
+ * @retval None
+ */
+__weak void HAL_TIM_IC_CaptureHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_IC_CaptureHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief PWM Pulse finished callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_PWM_PulseFinishedCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief PWM Pulse finished half complete callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_PWM_PulseFinishedHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_PWM_PulseFinishedHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Hall Trigger detection callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_TriggerCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Hall Trigger detection half complete callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_TriggerHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_TriggerHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Timer error callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIM_ErrorCallback could be implemented in the user file
+ */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Register a User TIM callback to be used instead of the weak predefined callback
+ * @param htim tim handle
+ * @param CallbackID ID of the callback to be registered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_TIM_BASE_MSPINIT_CB_ID Base MspInit Callback ID
+ * @arg @ref HAL_TIM_BASE_MSPDEINIT_CB_ID Base MspDeInit Callback ID
+ * @arg @ref HAL_TIM_IC_MSPINIT_CB_ID IC MspInit Callback ID
+ * @arg @ref HAL_TIM_IC_MSPDEINIT_CB_ID IC MspDeInit Callback ID
+ * @arg @ref HAL_TIM_OC_MSPINIT_CB_ID OC MspInit Callback ID
+ * @arg @ref HAL_TIM_OC_MSPDEINIT_CB_ID OC MspDeInit Callback ID
+ * @arg @ref HAL_TIM_PWM_MSPINIT_CB_ID PWM MspInit Callback ID
+ * @arg @ref HAL_TIM_PWM_MSPDEINIT_CB_ID PWM MspDeInit Callback ID
+ * @arg @ref HAL_TIM_ONE_PULSE_MSPINIT_CB_ID One Pulse MspInit Callback ID
+ * @arg @ref HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID One Pulse MspDeInit Callback ID
+ * @arg @ref HAL_TIM_ENCODER_MSPINIT_CB_ID Encoder MspInit Callback ID
+ * @arg @ref HAL_TIM_ENCODER_MSPDEINIT_CB_ID Encoder MspDeInit Callback ID
+ * @arg @ref HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID Hall Sensor MspInit Callback ID
+ * @arg @ref HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID Hall Sensor MspDeInit Callback ID
+ * @arg @ref HAL_TIM_PERIOD_ELAPSED_CB_ID Period Elapsed Callback ID
+ * @arg @ref HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID Period Elapsed half complete Callback ID
+ * @arg @ref HAL_TIM_TRIGGER_CB_ID Trigger Callback ID
+ * @arg @ref HAL_TIM_TRIGGER_HALF_CB_ID Trigger half complete Callback ID
+ * @arg @ref HAL_TIM_IC_CAPTURE_CB_ID Input Capture Callback ID
+ * @arg @ref HAL_TIM_IC_CAPTURE_HALF_CB_ID Input Capture half complete Callback ID
+ * @arg @ref HAL_TIM_OC_DELAY_ELAPSED_CB_ID Output Compare Delay Elapsed Callback ID
+ * @arg @ref HAL_TIM_PWM_PULSE_FINISHED_CB_ID PWM Pulse Finished Callback ID
+ * @arg @ref HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID PWM Pulse Finished half complete Callback ID
+ * @arg @ref HAL_TIM_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_TIM_COMMUTATION_CB_ID Commutation Callback ID
+ * @arg @ref HAL_TIM_COMMUTATION_HALF_CB_ID Commutation half complete Callback ID
+ * @arg @ref HAL_TIM_BREAK_CB_ID Break Callback ID
+ * @arg @ref HAL_TIM_BREAK2_CB_ID Break2 Callback ID
+ * @param pCallback pointer to the callback function
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_TIM_RegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID,
+ pTIM_CallbackTypeDef pCallback)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (pCallback == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ if (htim->State == HAL_TIM_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_TIM_BASE_MSPINIT_CB_ID :
+ htim->Base_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+ htim->Base_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_IC_MSPINIT_CB_ID :
+ htim->IC_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_IC_MSPDEINIT_CB_ID :
+ htim->IC_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_OC_MSPINIT_CB_ID :
+ htim->OC_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_OC_MSPDEINIT_CB_ID :
+ htim->OC_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_PWM_MSPINIT_CB_ID :
+ htim->PWM_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+ htim->PWM_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+ htim->OnePulse_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+ htim->OnePulse_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+ htim->Encoder_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+ htim->Encoder_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+ htim->HallSensor_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+ htim->HallSensor_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+ htim->PeriodElapsedCallback = pCallback;
+ break;
+
+ case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+ htim->PeriodElapsedHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_TIM_TRIGGER_CB_ID :
+ htim->TriggerCallback = pCallback;
+ break;
+
+ case HAL_TIM_TRIGGER_HALF_CB_ID :
+ htim->TriggerHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_TIM_IC_CAPTURE_CB_ID :
+ htim->IC_CaptureCallback = pCallback;
+ break;
+
+ case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+ htim->IC_CaptureHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+ htim->OC_DelayElapsedCallback = pCallback;
+ break;
+
+ case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+ htim->PWM_PulseFinishedCallback = pCallback;
+ break;
+
+ case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+ htim->PWM_PulseFinishedHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_TIM_ERROR_CB_ID :
+ htim->ErrorCallback = pCallback;
+ break;
+
+ case HAL_TIM_COMMUTATION_CB_ID :
+ htim->CommutationCallback = pCallback;
+ break;
+
+ case HAL_TIM_COMMUTATION_HALF_CB_ID :
+ htim->CommutationHalfCpltCallback = pCallback;
+ break;
+
+ case HAL_TIM_BREAK_CB_ID :
+ htim->BreakCallback = pCallback;
+ break;
+
+ case HAL_TIM_BREAK2_CB_ID :
+ htim->Break2Callback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_TIM_BASE_MSPINIT_CB_ID :
+ htim->Base_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+ htim->Base_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_IC_MSPINIT_CB_ID :
+ htim->IC_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_IC_MSPDEINIT_CB_ID :
+ htim->IC_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_OC_MSPINIT_CB_ID :
+ htim->OC_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_OC_MSPDEINIT_CB_ID :
+ htim->OC_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_PWM_MSPINIT_CB_ID :
+ htim->PWM_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+ htim->PWM_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+ htim->OnePulse_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+ htim->OnePulse_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+ htim->Encoder_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+ htim->Encoder_MspDeInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+ htim->HallSensor_MspInitCallback = pCallback;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+ htim->HallSensor_MspDeInitCallback = pCallback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Unregister a TIM callback
+ * TIM callback is redirected to the weak predefined callback
+ * @param htim tim handle
+ * @param CallbackID ID of the callback to be unregistered
+ * This parameter can be one of the following values:
+ * @arg @ref HAL_TIM_BASE_MSPINIT_CB_ID Base MspInit Callback ID
+ * @arg @ref HAL_TIM_BASE_MSPDEINIT_CB_ID Base MspDeInit Callback ID
+ * @arg @ref HAL_TIM_IC_MSPINIT_CB_ID IC MspInit Callback ID
+ * @arg @ref HAL_TIM_IC_MSPDEINIT_CB_ID IC MspDeInit Callback ID
+ * @arg @ref HAL_TIM_OC_MSPINIT_CB_ID OC MspInit Callback ID
+ * @arg @ref HAL_TIM_OC_MSPDEINIT_CB_ID OC MspDeInit Callback ID
+ * @arg @ref HAL_TIM_PWM_MSPINIT_CB_ID PWM MspInit Callback ID
+ * @arg @ref HAL_TIM_PWM_MSPDEINIT_CB_ID PWM MspDeInit Callback ID
+ * @arg @ref HAL_TIM_ONE_PULSE_MSPINIT_CB_ID One Pulse MspInit Callback ID
+ * @arg @ref HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID One Pulse MspDeInit Callback ID
+ * @arg @ref HAL_TIM_ENCODER_MSPINIT_CB_ID Encoder MspInit Callback ID
+ * @arg @ref HAL_TIM_ENCODER_MSPDEINIT_CB_ID Encoder MspDeInit Callback ID
+ * @arg @ref HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID Hall Sensor MspInit Callback ID
+ * @arg @ref HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID Hall Sensor MspDeInit Callback ID
+ * @arg @ref HAL_TIM_PERIOD_ELAPSED_CB_ID Period Elapsed Callback ID
+ * @arg @ref HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID Period Elapsed half complete Callback ID
+ * @arg @ref HAL_TIM_TRIGGER_CB_ID Trigger Callback ID
+ * @arg @ref HAL_TIM_TRIGGER_HALF_CB_ID Trigger half complete Callback ID
+ * @arg @ref HAL_TIM_IC_CAPTURE_CB_ID Input Capture Callback ID
+ * @arg @ref HAL_TIM_IC_CAPTURE_HALF_CB_ID Input Capture half complete Callback ID
+ * @arg @ref HAL_TIM_OC_DELAY_ELAPSED_CB_ID Output Compare Delay Elapsed Callback ID
+ * @arg @ref HAL_TIM_PWM_PULSE_FINISHED_CB_ID PWM Pulse Finished Callback ID
+ * @arg @ref HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID PWM Pulse Finished half complete Callback ID
+ * @arg @ref HAL_TIM_ERROR_CB_ID Error Callback ID
+ * @arg @ref HAL_TIM_COMMUTATION_CB_ID Commutation Callback ID
+ * @arg @ref HAL_TIM_COMMUTATION_HALF_CB_ID Commutation half complete Callback ID
+ * @arg @ref HAL_TIM_BREAK_CB_ID Break Callback ID
+ * @arg @ref HAL_TIM_BREAK2_CB_ID Break2 Callback ID
+ * @retval status
+ */
+HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_CallbackIDTypeDef CallbackID)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ if (htim->State == HAL_TIM_STATE_READY)
+ {
+ switch (CallbackID)
+ {
+ case HAL_TIM_BASE_MSPINIT_CB_ID :
+ /* Legacy weak Base MspInit Callback */
+ htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
+ break;
+
+ case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+ /* Legacy weak Base Msp DeInit Callback */
+ htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit;
+ break;
+
+ case HAL_TIM_IC_MSPINIT_CB_ID :
+ /* Legacy weak IC Msp Init Callback */
+ htim->IC_MspInitCallback = HAL_TIM_IC_MspInit;
+ break;
+
+ case HAL_TIM_IC_MSPDEINIT_CB_ID :
+ /* Legacy weak IC Msp DeInit Callback */
+ htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit;
+ break;
+
+ case HAL_TIM_OC_MSPINIT_CB_ID :
+ /* Legacy weak OC Msp Init Callback */
+ htim->OC_MspInitCallback = HAL_TIM_OC_MspInit;
+ break;
+
+ case HAL_TIM_OC_MSPDEINIT_CB_ID :
+ /* Legacy weak OC Msp DeInit Callback */
+ htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit;
+ break;
+
+ case HAL_TIM_PWM_MSPINIT_CB_ID :
+ /* Legacy weak PWM Msp Init Callback */
+ htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit;
+ break;
+
+ case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+ /* Legacy weak PWM Msp DeInit Callback */
+ htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+ /* Legacy weak One Pulse Msp Init Callback */
+ htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+ /* Legacy weak One Pulse Msp DeInit Callback */
+ htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit;
+ break;
+
+ case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+ /* Legacy weak Encoder Msp Init Callback */
+ htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit;
+ break;
+
+ case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+ /* Legacy weak Encoder Msp DeInit Callback */
+ htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+ /* Legacy weak Hall Sensor Msp Init Callback */
+ htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+ /* Legacy weak Hall Sensor Msp DeInit Callback */
+ htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+ break;
+
+ case HAL_TIM_PERIOD_ELAPSED_CB_ID :
+ /* Legacy weak Period Elapsed Callback */
+ htim->PeriodElapsedCallback = HAL_TIM_PeriodElapsedCallback;
+ break;
+
+ case HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID :
+ /* Legacy weak Period Elapsed half complete Callback */
+ htim->PeriodElapsedHalfCpltCallback = HAL_TIM_PeriodElapsedHalfCpltCallback;
+ break;
+
+ case HAL_TIM_TRIGGER_CB_ID :
+ /* Legacy weak Trigger Callback */
+ htim->TriggerCallback = HAL_TIM_TriggerCallback;
+ break;
+
+ case HAL_TIM_TRIGGER_HALF_CB_ID :
+ /* Legacy weak Trigger half complete Callback */
+ htim->TriggerHalfCpltCallback = HAL_TIM_TriggerHalfCpltCallback;
+ break;
+
+ case HAL_TIM_IC_CAPTURE_CB_ID :
+ /* Legacy weak IC Capture Callback */
+ htim->IC_CaptureCallback = HAL_TIM_IC_CaptureCallback;
+ break;
+
+ case HAL_TIM_IC_CAPTURE_HALF_CB_ID :
+ /* Legacy weak IC Capture half complete Callback */
+ htim->IC_CaptureHalfCpltCallback = HAL_TIM_IC_CaptureHalfCpltCallback;
+ break;
+
+ case HAL_TIM_OC_DELAY_ELAPSED_CB_ID :
+ /* Legacy weak OC Delay Elapsed Callback */
+ htim->OC_DelayElapsedCallback = HAL_TIM_OC_DelayElapsedCallback;
+ break;
+
+ case HAL_TIM_PWM_PULSE_FINISHED_CB_ID :
+ /* Legacy weak PWM Pulse Finished Callback */
+ htim->PWM_PulseFinishedCallback = HAL_TIM_PWM_PulseFinishedCallback;
+ break;
+
+ case HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID :
+ /* Legacy weak PWM Pulse Finished half complete Callback */
+ htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback;
+ break;
+
+ case HAL_TIM_ERROR_CB_ID :
+ /* Legacy weak Error Callback */
+ htim->ErrorCallback = HAL_TIM_ErrorCallback;
+ break;
+
+ case HAL_TIM_COMMUTATION_CB_ID :
+ /* Legacy weak Commutation Callback */
+ htim->CommutationCallback = HAL_TIMEx_CommutCallback;
+ break;
+
+ case HAL_TIM_COMMUTATION_HALF_CB_ID :
+ /* Legacy weak Commutation half complete Callback */
+ htim->CommutationHalfCpltCallback = HAL_TIMEx_CommutHalfCpltCallback;
+ break;
+
+ case HAL_TIM_BREAK_CB_ID :
+ /* Legacy weak Break Callback */
+ htim->BreakCallback = HAL_TIMEx_BreakCallback;
+ break;
+
+ case HAL_TIM_BREAK2_CB_ID :
+ /* Legacy weak Break2 Callback */
+ htim->Break2Callback = HAL_TIMEx_Break2Callback;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ switch (CallbackID)
+ {
+ case HAL_TIM_BASE_MSPINIT_CB_ID :
+ /* Legacy weak Base MspInit Callback */
+ htim->Base_MspInitCallback = HAL_TIM_Base_MspInit;
+ break;
+
+ case HAL_TIM_BASE_MSPDEINIT_CB_ID :
+ /* Legacy weak Base Msp DeInit Callback */
+ htim->Base_MspDeInitCallback = HAL_TIM_Base_MspDeInit;
+ break;
+
+ case HAL_TIM_IC_MSPINIT_CB_ID :
+ /* Legacy weak IC Msp Init Callback */
+ htim->IC_MspInitCallback = HAL_TIM_IC_MspInit;
+ break;
+
+ case HAL_TIM_IC_MSPDEINIT_CB_ID :
+ /* Legacy weak IC Msp DeInit Callback */
+ htim->IC_MspDeInitCallback = HAL_TIM_IC_MspDeInit;
+ break;
+
+ case HAL_TIM_OC_MSPINIT_CB_ID :
+ /* Legacy weak OC Msp Init Callback */
+ htim->OC_MspInitCallback = HAL_TIM_OC_MspInit;
+ break;
+
+ case HAL_TIM_OC_MSPDEINIT_CB_ID :
+ /* Legacy weak OC Msp DeInit Callback */
+ htim->OC_MspDeInitCallback = HAL_TIM_OC_MspDeInit;
+ break;
+
+ case HAL_TIM_PWM_MSPINIT_CB_ID :
+ /* Legacy weak PWM Msp Init Callback */
+ htim->PWM_MspInitCallback = HAL_TIM_PWM_MspInit;
+ break;
+
+ case HAL_TIM_PWM_MSPDEINIT_CB_ID :
+ /* Legacy weak PWM Msp DeInit Callback */
+ htim->PWM_MspDeInitCallback = HAL_TIM_PWM_MspDeInit;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPINIT_CB_ID :
+ /* Legacy weak One Pulse Msp Init Callback */
+ htim->OnePulse_MspInitCallback = HAL_TIM_OnePulse_MspInit;
+ break;
+
+ case HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID :
+ /* Legacy weak One Pulse Msp DeInit Callback */
+ htim->OnePulse_MspDeInitCallback = HAL_TIM_OnePulse_MspDeInit;
+ break;
+
+ case HAL_TIM_ENCODER_MSPINIT_CB_ID :
+ /* Legacy weak Encoder Msp Init Callback */
+ htim->Encoder_MspInitCallback = HAL_TIM_Encoder_MspInit;
+ break;
+
+ case HAL_TIM_ENCODER_MSPDEINIT_CB_ID :
+ /* Legacy weak Encoder Msp DeInit Callback */
+ htim->Encoder_MspDeInitCallback = HAL_TIM_Encoder_MspDeInit;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID :
+ /* Legacy weak Hall Sensor Msp Init Callback */
+ htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
+ break;
+
+ case HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID :
+ /* Legacy weak Hall Sensor Msp DeInit Callback */
+ htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+ break;
+
+ default :
+ /* Return error status */
+ status = HAL_ERROR;
+ break;
+ }
+ }
+ else
+ {
+ /* Return error status */
+ status = HAL_ERROR;
+ }
+
+ return status;
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Exported_Functions_Group10 TIM Peripheral State functions
+ * @brief TIM Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the TIM Base handle state.
+ * @param htim TIM Base handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM OC handle state.
+ * @param htim TIM Output Compare handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM PWM handle state.
+ * @param htim TIM handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Input Capture handle state.
+ * @param htim TIM IC handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM One Pulse Mode handle state.
+ * @param htim TIM OPM handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Encoder Mode handle state.
+ * @param htim TIM Encoder Interface handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return the TIM Encoder Mode handle state.
+ * @param htim TIM handle
+ * @retval Active channel
+ */
+HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim)
+{
+ return htim->Channel;
+}
+
+/**
+ * @brief Return actual state of the TIM channel.
+ * @param htim TIM handle
+ * @param Channel TIM Channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1
+ * @arg TIM_CHANNEL_2: TIM Channel 2
+ * @arg TIM_CHANNEL_3: TIM Channel 3
+ * @arg TIM_CHANNEL_4: TIM Channel 4
+ * @arg TIM_CHANNEL_5: TIM Channel 5
+ * @arg TIM_CHANNEL_6: TIM Channel 6
+ * @retval TIM Channel state
+ */
+HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_TIM_ChannelStateTypeDef channel_state;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
+
+ channel_state = TIM_CHANNEL_STATE_GET(htim, Channel);
+
+ return channel_state;
+}
+
+/**
+ * @brief Return actual state of a DMA burst operation.
+ * @param htim TIM handle
+ * @retval DMA burst state
+ */
+HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance));
+
+ return htim->DMABurstState;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIM_Private_Functions TIM Private Functions
+ * @{
+ */
+
+/**
+ * @brief TIM DMA error callback
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIM_DMAError(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else
+ {
+ htim->State = HAL_TIM_STATE_READY;
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->ErrorCallback(htim);
+#else
+ HAL_TIM_ErrorCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief TIM DMA Delay Pulse complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief TIM DMA Delay Pulse half complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIM_DMADelayPulseHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PWM_PulseFinishedHalfCpltCallback(htim);
+#else
+ HAL_TIM_PWM_PulseFinishedHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief TIM DMA Capture complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureCallback(htim);
+#else
+ HAL_TIM_IC_CaptureCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief TIM DMA Capture half complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIM_DMACaptureHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->IC_CaptureHalfCpltCallback(htim);
+#else
+ HAL_TIM_IC_CaptureHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief TIM DMA Period Elapse complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (htim->hdma[TIM_DMA_ID_UPDATE]->Init.Mode == DMA_NORMAL)
+ {
+ htim->State = HAL_TIM_STATE_READY;
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PeriodElapsedCallback(htim);
+#else
+ HAL_TIM_PeriodElapsedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief TIM DMA Period Elapse half complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMAPeriodElapsedHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PeriodElapsedHalfCpltCallback(htim);
+#else
+ HAL_TIM_PeriodElapsedHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief TIM DMA Trigger callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (htim->hdma[TIM_DMA_ID_TRIGGER]->Init.Mode == DMA_NORMAL)
+ {
+ htim->State = HAL_TIM_STATE_READY;
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->TriggerCallback(htim);
+#else
+ HAL_TIM_TriggerCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief TIM DMA Trigger half complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->TriggerHalfCpltCallback(htim);
+#else
+ HAL_TIM_TriggerHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief Time Base configuration
+ * @param TIMx TIM peripheral
+ * @param Structure TIM Base configuration structure
+ * @retval None
+ */
+void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure)
+{
+ uint32_t tmpcr1;
+ tmpcr1 = TIMx->CR1;
+
+ /* Set TIM Time Base Unit parameters ---------------------------------------*/
+ if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
+ {
+ /* Select the Counter Mode */
+ tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
+ tmpcr1 |= Structure->CounterMode;
+ }
+
+ if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
+ {
+ /* Set the clock division */
+ tmpcr1 &= ~TIM_CR1_CKD;
+ tmpcr1 |= (uint32_t)Structure->ClockDivision;
+ }
+
+ /* Set the auto-reload preload */
+ MODIFY_REG(tmpcr1, TIM_CR1_ARPE, Structure->AutoReloadPreload);
+
+ /* Set the Autoreload value */
+ TIMx->ARR = (uint32_t)Structure->Period ;
+
+ /* Set the Prescaler value */
+ TIMx->PSC = Structure->Prescaler;
+
+ if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
+ {
+ /* Set the Repetition Counter value */
+ TIMx->RCR = Structure->RepetitionCounter;
+ }
+
+ /* Disable Update Event (UEV) with Update Generation (UG)
+ by changing Update Request Source (URS) to avoid Update flag (UIF) */
+ SET_BIT(TIMx->CR1, TIM_CR1_URS);
+
+ /* Generate an update event to reload the Prescaler
+ and the repetition counter (only for advanced timer) value immediately */
+ TIMx->EGR = TIM_EGR_UG;
+
+ TIMx->CR1 = tmpcr1;
+}
+
+/**
+ * @brief Timer Output Compare 1 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The output configuration structure
+ * @retval None
+ */
+static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC1E;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR1;
+
+ /* Reset the Output Compare Mode Bits */
+ tmpccmrx &= ~TIM_CCMR1_OC1M;
+ tmpccmrx &= ~TIM_CCMR1_CC1S;
+ /* Select the Output Compare Mode */
+ tmpccmrx |= OC_Config->OCMode;
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC1P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= OC_Config->OCPolarity;
+
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+ /* Disable the Channel 1N: Reset the CC1NE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC1NE;
+
+ /* Reset the Output N Polarity level */
+ tmpccer &= ~TIM_CCER_CC1NP;
+ /* Set the Output N Polarity */
+ tmpccer |= OC_Config->OCNPolarity;
+ }
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare and Output Compare N IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS1;
+ tmpcr2 &= ~TIM_CR2_OIS1N;
+ /* Set the Output Idle state */
+ tmpcr2 |= OC_Config->OCIdleState;
+ /* Set the Output N Idle state */
+ tmpcr2 |= OC_Config->OCNIdleState;
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR1 */
+ TIMx->CCMR1 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR1 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 2 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The output configuration structure
+ * @retval None
+ */
+void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2E;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR1;
+
+ /* Reset the Output Compare mode and Capture/Compare selection Bits */
+ tmpccmrx &= ~TIM_CCMR1_OC2M;
+ tmpccmrx &= ~TIM_CCMR1_CC2S;
+
+ /* Select the Output Compare Mode */
+ tmpccmrx |= (OC_Config->OCMode << 8U);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC2P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 4U);
+
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2))
+ {
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+ /* Disable the Channel 2N: Reset the CC2NE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2NE;
+
+ /* Reset the Output N Polarity level */
+ tmpccer &= ~TIM_CCER_CC2NP;
+ /* Set the Output N Polarity */
+ tmpccer |= (OC_Config->OCNPolarity << 4U);
+ }
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare and Output Compare N IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS2;
+ tmpcr2 &= ~TIM_CR2_OIS2N;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 2U);
+ /* Set the Output N Idle state */
+ tmpcr2 |= (OC_Config->OCNIdleState << 2U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR1 */
+ TIMx->CCMR1 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR2 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 3 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The output configuration structure
+ * @retval None
+ */
+static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 3: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC3E;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmrx = TIMx->CCMR2;
+
+ /* Reset the Output Compare mode and Capture/Compare selection Bits */
+ tmpccmrx &= ~TIM_CCMR2_OC3M;
+ tmpccmrx &= ~TIM_CCMR2_CC3S;
+ /* Select the Output Compare Mode */
+ tmpccmrx |= OC_Config->OCMode;
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC3P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 8U);
+
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3))
+ {
+ assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
+
+ /* Disable the Channel 3N: Reset the CC3NE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC3NE;
+
+ /* Reset the Output N Polarity level */
+ tmpccer &= ~TIM_CCER_CC3NP;
+ /* Set the Output N Polarity */
+ tmpccer |= (OC_Config->OCNPolarity << 8U);
+ }
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare and Output Compare N IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS3;
+ tmpcr2 &= ~TIM_CR2_OIS3N;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 4U);
+ /* Set the Output N Idle state */
+ tmpcr2 |= (OC_Config->OCNIdleState << 4U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR2 */
+ TIMx->CCMR2 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR3 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 4 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The output configuration structure
+ * @retval None
+ */
+static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 4: Reset the CC4E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC4E;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmrx = TIMx->CCMR2;
+
+ /* Reset the Output Compare mode and Capture/Compare selection Bits */
+ tmpccmrx &= ~TIM_CCMR2_OC4M;
+ tmpccmrx &= ~TIM_CCMR2_CC4S;
+
+ /* Select the Output Compare Mode */
+ tmpccmrx |= (OC_Config->OCMode << 8U);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC4P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 12U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Check parameters */
+ assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
+
+ /* Reset the Output Compare IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS4;
+
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 6U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR2 */
+ TIMx->CCMR2 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR4 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 5 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The output configuration structure
+ * @retval None
+ */
+static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx,
+ const TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the output: Reset the CCxE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC5E;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR3;
+
+ /* Reset the Output Compare Mode Bits */
+ tmpccmrx &= ~(TIM_CCMR3_OC5M);
+ /* Select the Output Compare Mode */
+ tmpccmrx |= OC_Config->OCMode;
+
+ /* Reset the Output Polarity level */
+ tmpccer &= ~TIM_CCER_CC5P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 16U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Reset the Output Compare IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS5;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 8U);
+ }
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR3 */
+ TIMx->CCMR3 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR5 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Timer Output Compare 6 configuration
+ * @param TIMx to select the TIM peripheral
+ * @param OC_Config The output configuration structure
+ * @retval None
+ */
+static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx,
+ const TIM_OC_InitTypeDef *OC_Config)
+{
+ uint32_t tmpccmrx;
+ uint32_t tmpccer;
+ uint32_t tmpcr2;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the output: Reset the CCxE Bit */
+ TIMx->CCER &= ~TIM_CCER_CC6E;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = TIMx->CR2;
+ /* Get the TIMx CCMR1 register value */
+ tmpccmrx = TIMx->CCMR3;
+
+ /* Reset the Output Compare Mode Bits */
+ tmpccmrx &= ~(TIM_CCMR3_OC6M);
+ /* Select the Output Compare Mode */
+ tmpccmrx |= (OC_Config->OCMode << 8U);
+
+ /* Reset the Output Polarity level */
+ tmpccer &= (uint32_t)~TIM_CCER_CC6P;
+ /* Set the Output Compare Polarity */
+ tmpccer |= (OC_Config->OCPolarity << 20U);
+
+ if (IS_TIM_BREAK_INSTANCE(TIMx))
+ {
+ /* Reset the Output Compare IDLE State */
+ tmpcr2 &= ~TIM_CR2_OIS6;
+ /* Set the Output Idle state */
+ tmpcr2 |= (OC_Config->OCIdleState << 10U);
+ }
+
+ /* Write to TIMx CR2 */
+ TIMx->CR2 = tmpcr2;
+
+ /* Write to TIMx CCMR3 */
+ TIMx->CCMR3 = tmpccmrx;
+
+ /* Set the Capture Compare Register value */
+ TIMx->CCR6 = OC_Config->Pulse;
+
+ /* Write to TIMx CCER */
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Slave Timer configuration function
+ * @param htim TIM handle
+ * @param sSlaveConfig Slave timer configuration
+ * @retval None
+ */
+static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim,
+ const TIM_SlaveConfigTypeDef *sSlaveConfig)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = htim->Instance->SMCR;
+
+ /* Reset the Trigger Selection Bits */
+ tmpsmcr &= ~TIM_SMCR_TS;
+ /* Set the Input Trigger source */
+ tmpsmcr |= sSlaveConfig->InputTrigger;
+
+ /* Reset the slave mode Bits */
+ tmpsmcr &= ~TIM_SMCR_SMS;
+ /* Set the slave mode */
+ tmpsmcr |= sSlaveConfig->SlaveMode;
+
+ /* Write to TIMx SMCR */
+ htim->Instance->SMCR = tmpsmcr;
+
+ /* Configure the trigger prescaler, filter, and polarity */
+ switch (sSlaveConfig->InputTrigger)
+ {
+ case TIM_TS_ETRF:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TRIGGERPRESCALER(sSlaveConfig->TriggerPrescaler));
+ assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+ assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+ /* Configure the ETR Trigger source */
+ TIM_ETR_SetConfig(htim->Instance,
+ sSlaveConfig->TriggerPrescaler,
+ sSlaveConfig->TriggerPolarity,
+ sSlaveConfig->TriggerFilter);
+ break;
+ }
+
+ case TIM_TS_TI1F_ED:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+ if (sSlaveConfig->SlaveMode == TIM_SLAVEMODE_GATED)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ tmpccer = htim->Instance->CCER;
+ htim->Instance->CCER &= ~TIM_CCER_CC1E;
+ tmpccmr1 = htim->Instance->CCMR1;
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC1F;
+ tmpccmr1 |= ((sSlaveConfig->TriggerFilter) << 4U);
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ htim->Instance->CCMR1 = tmpccmr1;
+ htim->Instance->CCER = tmpccer;
+ break;
+ }
+
+ case TIM_TS_TI1FP1:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+ assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+ /* Configure TI1 Filter and Polarity */
+ TIM_TI1_ConfigInputStage(htim->Instance,
+ sSlaveConfig->TriggerPolarity,
+ sSlaveConfig->TriggerFilter);
+ break;
+ }
+
+ case TIM_TS_TI2FP2:
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity));
+ assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter));
+
+ /* Configure TI2 Filter and Polarity */
+ TIM_TI2_ConfigInputStage(htim->Instance,
+ sSlaveConfig->TriggerPolarity,
+ sSlaveConfig->TriggerFilter);
+ break;
+ }
+
+ case TIM_TS_ITR0:
+ case TIM_TS_ITR1:
+ case TIM_TS_ITR2:
+ case TIM_TS_ITR3:
+ case TIM_TS_ITR4:
+ case TIM_TS_ITR5:
+ case TIM_TS_ITR6:
+ case TIM_TS_ITR7:
+ case TIM_TS_ITR8:
+ case TIM_TS_ITR9:
+ case TIM_TS_ITR10:
+ case TIM_TS_ITR11:
+ case TIM_TS_ITR12:
+ case TIM_TS_ITR13:
+ {
+ /* Check the parameter */
+ assert_param(IS_TIM_CC2_INSTANCE(htim->Instance));
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Configure the TI1 as Input.
+ * @param TIMx to select the TIM peripheral.
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 1 is selected to be connected to IC1.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 1 is selected to be connected to IC2.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 1 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI2FP1
+ * (on channel2 path) is used as the input signal. Therefore CCMR1 must be
+ * protected against un-initialized filter and polarity values.
+ */
+void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC1E;
+ /* Disable the Channel 1N: Reset the CC1NE Bit */
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
+ {
+ TIMx->CCER &= ~TIM_CCER_CC1NE;
+ }
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = TIMx->CCMR1;
+
+ /* Select the Input */
+ if (IS_TIM_CC2_INSTANCE(TIMx) != RESET)
+ {
+ tmpccmr1 &= ~TIM_CCMR1_CC1S;
+ tmpccmr1 |= TIM_ICSelection;
+ }
+ else
+ {
+ tmpccmr1 |= TIM_CCMR1_CC1S_0;
+ }
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC1F;
+ tmpccmr1 |= ((TIM_ICFilter << 4U) & TIM_CCMR1_IC1F);
+
+ /* Select the Polarity and set the CC1E Bit */
+ tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+ tmpccer |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the Polarity and Filter for TI1.
+ * @param TIMx to select the TIM peripheral.
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 1: Reset the CC1E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC1E;
+ /* Disable the Channel 1N: Reset the CC1NE Bit */
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))
+ {
+ TIMx->CCER &= ~TIM_CCER_CC1NE;
+ }
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = TIMx->CCMR1;
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC1F;
+ tmpccmr1 |= (TIM_ICFilter << 4U);
+
+ /* Select the Polarity and set the CC1E Bit */
+ tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
+ tmpccer |= TIM_ICPolarity;
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the TI2 as Input.
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 2 is selected to be connected to IC2.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 2 is selected to be connected to IC1.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 2 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI1FP2
+ * (on channel1 path) is used as the input signal. Therefore CCMR1 must be
+ * protected against un-initialized filter and polarity values.
+ */
+static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2E;
+ /* Disable the Channel 2N: Reset the CC2NE Bit */
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2))
+ {
+ TIMx->CCER &= ~TIM_CCER_CC2NE;
+ }
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = TIMx->CCMR1;
+
+ /* Select the Input */
+ tmpccmr1 &= ~TIM_CCMR1_CC2S;
+ tmpccmr1 |= (TIM_ICSelection << 8U);
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC2F;
+ tmpccmr1 |= ((TIM_ICFilter << 12U) & TIM_CCMR1_IC2F);
+
+ /* Select the Polarity and set the CC2E Bit */
+ tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= ((TIM_ICPolarity << 4U) & (TIM_CCER_CC2P | TIM_CCER_CC2NP));
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1 ;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the Polarity and Filter for TI2.
+ * @param TIMx to select the TIM peripheral.
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ */
+static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr1;
+ uint32_t tmpccer;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 2: Reset the CC2E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC2E;
+ /* Disable the Channel 2N: Reset the CC2NE Bit */
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2))
+ {
+ TIMx->CCER &= ~TIM_CCER_CC2NE;
+ }
+
+ /* Get the TIMx CCMR1 register value */
+ tmpccmr1 = TIMx->CCMR1;
+
+ /* Set the filter */
+ tmpccmr1 &= ~TIM_CCMR1_IC2F;
+ tmpccmr1 |= (TIM_ICFilter << 12U);
+
+ /* Select the Polarity and set the CC2E Bit */
+ tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
+ tmpccer |= (TIM_ICPolarity << 4U);
+
+ /* Write to TIMx CCMR1 and CCER registers */
+ TIMx->CCMR1 = tmpccmr1 ;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the TI3 as Input.
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 3 is selected to be connected to IC3.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 3 is selected to be connected to IC4.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 3 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @retval None
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI3FP4
+ * (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+ * protected against un-initialized filter and polarity values.
+ */
+static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr2;
+ uint32_t tmpccer;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 3: Reset the CC3E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC3E;
+ /* Disable the Channel 3N: Reset the CC3NE Bit */
+ if (IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3))
+ {
+ TIMx->CCER &= ~TIM_CCER_CC3NE;
+ }
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmr2 = TIMx->CCMR2;
+
+ /* Select the Input */
+ tmpccmr2 &= ~TIM_CCMR2_CC3S;
+ tmpccmr2 |= TIM_ICSelection;
+
+ /* Set the filter */
+ tmpccmr2 &= ~TIM_CCMR2_IC3F;
+ tmpccmr2 |= ((TIM_ICFilter << 4U) & TIM_CCMR2_IC3F);
+
+ /* Select the Polarity and set the CC3E Bit */
+ tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
+ tmpccer |= ((TIM_ICPolarity << 8U) & (TIM_CCER_CC3P | TIM_CCER_CC3NP));
+
+ /* Write to TIMx CCMR2 and CCER registers */
+ TIMx->CCMR2 = tmpccmr2;
+ TIMx->CCER = tmpccer;
+}
+
+/**
+ * @brief Configure the TI4 as Input.
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ICPolarity The Input Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICPOLARITY_RISING
+ * @arg TIM_ICPOLARITY_FALLING
+ * @arg TIM_ICPOLARITY_BOTHEDGE
+ * @param TIM_ICSelection specifies the input to be used.
+ * This parameter can be one of the following values:
+ * @arg TIM_ICSELECTION_DIRECTTI: TIM Input 4 is selected to be connected to IC4.
+ * @arg TIM_ICSELECTION_INDIRECTTI: TIM Input 4 is selected to be connected to IC3.
+ * @arg TIM_ICSELECTION_TRC: TIM Input 4 is selected to be connected to TRC.
+ * @param TIM_ICFilter Specifies the Input Capture Filter.
+ * This parameter must be a value between 0x00 and 0x0F.
+ * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI4FP3
+ * (on channel1 path) is used as the input signal. Therefore CCMR2 must be
+ * protected against un-initialized filter and polarity values.
+ * @retval None
+ */
+static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection,
+ uint32_t TIM_ICFilter)
+{
+ uint32_t tmpccmr2;
+ uint32_t tmpccer;
+
+ /* Get the TIMx CCER register value */
+ tmpccer = TIMx->CCER;
+
+ /* Disable the Channel 4: Reset the CC4E Bit */
+ TIMx->CCER &= ~TIM_CCER_CC4E;
+
+ /* Get the TIMx CCMR2 register value */
+ tmpccmr2 = TIMx->CCMR2;
+
+ /* Select the Input */
+ tmpccmr2 &= ~TIM_CCMR2_CC4S;
+ tmpccmr2 |= (TIM_ICSelection << 8U);
+
+ /* Set the filter */
+ tmpccmr2 &= ~TIM_CCMR2_IC4F;
+ tmpccmr2 |= ((TIM_ICFilter << 12U) & TIM_CCMR2_IC4F);
+
+ /* Select the Polarity and set the CC4E Bit */
+ tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP);
+ tmpccer |= ((TIM_ICPolarity << 12U) & (TIM_CCER_CC4P | TIM_CCER_CC4NP));
+
+ /* Write to TIMx CCMR2 and CCER registers */
+ TIMx->CCMR2 = tmpccmr2;
+ TIMx->CCER = tmpccer ;
+}
+
+/**
+ * @brief Selects the Input Trigger source
+ * @param TIMx to select the TIM peripheral
+ * @param InputTriggerSource The Input Trigger source.
+ * This parameter can be one of the following values:
+ * @arg TIM_TS_ITR0: Internal Trigger 0
+ * @arg TIM_TS_ITR1: Internal Trigger 1
+ * @arg TIM_TS_ITR2: Internal Trigger 2
+ * @arg TIM_TS_ITR3: Internal Trigger 3
+ * @arg TIM_TS_ITR4: Internal Trigger 4 (*)
+ * @arg TIM_TS_ITR5: Internal Trigger 5
+ * @arg TIM_TS_ITR6: Internal Trigger 6
+ * @arg TIM_TS_ITR7: Internal Trigger 7
+ * @arg TIM_TS_ITR8: Internal Trigger 8 (*)
+ * @arg TIM_TS_ITR9: Internal Trigger 9 (*)
+ * @arg TIM_TS_ITR10: Internal Trigger 10 (*)
+ * @arg TIM_TS_ITR11: Internal Trigger 11 (*)
+ * @arg TIM_TS_ITR12: Internal Trigger 12 (*)
+ * @arg TIM_TS_ITR13: Internal Trigger 13 (*)
+ * @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
+ *
+ * (*) Value not defined in all devices.
+ *
+ * @retval None
+ */
+static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint32_t InputTriggerSource)
+{
+ uint32_t tmpsmcr;
+
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = TIMx->SMCR;
+ /* Reset the TS Bits */
+ tmpsmcr &= ~TIM_SMCR_TS;
+ /* Set the Input Trigger source and the slave mode*/
+ tmpsmcr |= (InputTriggerSource | TIM_SLAVEMODE_EXTERNAL1);
+ /* Write to TIMx SMCR */
+ TIMx->SMCR = tmpsmcr;
+}
+/**
+ * @brief Configures the TIMx External Trigger (ETR).
+ * @param TIMx to select the TIM peripheral
+ * @param TIM_ExtTRGPrescaler The external Trigger Prescaler.
+ * This parameter can be one of the following values:
+ * @arg TIM_ETRPRESCALER_DIV1: ETRP Prescaler OFF.
+ * @arg TIM_ETRPRESCALER_DIV2: ETRP frequency divided by 2.
+ * @arg TIM_ETRPRESCALER_DIV4: ETRP frequency divided by 4.
+ * @arg TIM_ETRPRESCALER_DIV8: ETRP frequency divided by 8.
+ * @param TIM_ExtTRGPolarity The external Trigger Polarity.
+ * This parameter can be one of the following values:
+ * @arg TIM_ETRPOLARITY_INVERTED: active low or falling edge active.
+ * @arg TIM_ETRPOLARITY_NONINVERTED: active high or rising edge active.
+ * @param ExtTRGFilter External Trigger Filter.
+ * This parameter must be a value between 0x00 and 0x0F
+ * @retval None
+ */
+void TIM_ETR_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler,
+ uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter)
+{
+ uint32_t tmpsmcr;
+
+ tmpsmcr = TIMx->SMCR;
+
+ /* Reset the ETR Bits */
+ tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP);
+
+ /* Set the Prescaler, the Filter value and the Polarity */
+ tmpsmcr |= (uint32_t)(TIM_ExtTRGPrescaler | (TIM_ExtTRGPolarity | (ExtTRGFilter << 8U)));
+
+ /* Write to TIMx SMCR */
+ TIMx->SMCR = tmpsmcr;
+}
+
+/**
+ * @brief Enables or disables the TIM Capture Compare Channel x.
+ * @param TIMx to select the TIM peripheral
+ * @param Channel specifies the TIM Channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @arg TIM_CHANNEL_4: TIM Channel 4 selected
+ * @arg TIM_CHANNEL_5: TIM Channel 5 selected
+ * @arg TIM_CHANNEL_6: TIM Channel 6 selected
+ * @param ChannelState specifies the TIM Channel CCxE bit new state.
+ * This parameter can be: TIM_CCx_ENABLE or TIM_CCx_DISABLE.
+ * @retval None
+ */
+void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState)
+{
+ uint32_t tmp;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CC1_INSTANCE(TIMx));
+ assert_param(IS_TIM_CHANNELS(Channel));
+
+ tmp = TIM_CCER_CC1E << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
+
+ /* Reset the CCxE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
+}
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+/**
+ * @brief Reset interrupt callbacks to the legacy weak callbacks.
+ * @param htim pointer to a TIM_HandleTypeDef structure that contains
+ * the configuration information for TIM module.
+ * @retval None
+ */
+void TIM_ResetCallback(TIM_HandleTypeDef *htim)
+{
+ /* Reset the TIM callback to the legacy weak callbacks */
+ htim->PeriodElapsedCallback = HAL_TIM_PeriodElapsedCallback;
+ htim->PeriodElapsedHalfCpltCallback = HAL_TIM_PeriodElapsedHalfCpltCallback;
+ htim->TriggerCallback = HAL_TIM_TriggerCallback;
+ htim->TriggerHalfCpltCallback = HAL_TIM_TriggerHalfCpltCallback;
+ htim->IC_CaptureCallback = HAL_TIM_IC_CaptureCallback;
+ htim->IC_CaptureHalfCpltCallback = HAL_TIM_IC_CaptureHalfCpltCallback;
+ htim->OC_DelayElapsedCallback = HAL_TIM_OC_DelayElapsedCallback;
+ htim->PWM_PulseFinishedCallback = HAL_TIM_PWM_PulseFinishedCallback;
+ htim->PWM_PulseFinishedHalfCpltCallback = HAL_TIM_PWM_PulseFinishedHalfCpltCallback;
+ htim->ErrorCallback = HAL_TIM_ErrorCallback;
+ htim->CommutationCallback = HAL_TIMEx_CommutCallback;
+ htim->CommutationHalfCpltCallback = HAL_TIMEx_CommutHalfCpltCallback;
+ htim->BreakCallback = HAL_TIMEx_BreakCallback;
+ htim->Break2Callback = HAL_TIMEx_Break2Callback;
+}
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
new file mode 100755
index 0000000..b7f6787
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
@@ -0,0 +1,2921 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_hal_tim_ex.c
+ * @author MCD Application Team
+ * @brief TIM HAL module driver.
+ * This file provides firmware functions to manage the following
+ * functionalities of the Timer Extended peripheral:
+ * + Time Hall Sensor Interface Initialization
+ * + Time Hall Sensor Interface Start
+ * + Time Complementary signal break and dead time configuration
+ * + Time Master and Slave synchronization configuration
+ * + Time Output Compare/PWM Channel Configuration (for channels 5 and 6)
+ * + Timer remapping capabilities configuration
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### TIMER Extended features #####
+ ==============================================================================
+ [..]
+ The Timer Extended features include:
+ (#) Complementary outputs with programmable dead-time for :
+ (++) Output Compare
+ (++) PWM generation (Edge and Center-aligned Mode)
+ (++) One-pulse mode output
+ (#) Synchronization circuit to control the timer with external signals and to
+ interconnect several timers together.
+ (#) Break input to put the timer output signals in reset state or in a known state.
+ (#) Supports incremental (quadrature) encoder and hall-sensor circuitry for
+ positioning purposes
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Initialize the TIM low level resources by implementing the following functions
+ depending on the selected feature:
+ (++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit()
+
+ (#) Initialize the TIM low level resources :
+ (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
+ (##) TIM pins configuration
+ (+++) Enable the clock for the TIM GPIOs using the following function:
+ __HAL_RCC_GPIOx_CLK_ENABLE();
+ (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
+
+ (#) The external Clock can be configured, if needed (the default clock is the
+ internal clock from the APBx), using the following function:
+ HAL_TIM_ConfigClockSource, the clock configuration should be done before
+ any start function.
+
+ (#) Configure the TIM in the desired functioning mode using one of the
+ initialization function of this driver:
+ (++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutEvent(): to use the
+ Timer Hall Sensor Interface and the commutation event with the corresponding
+ Interrupt and DMA request if needed (Note that One Timer is used to interface
+ with the Hall sensor Interface and another Timer should be used to use
+ the commutation event).
+
+ (#) Activate the TIM peripheral using one of the start functions:
+ (++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(),
+ HAL_TIMEx_OCN_Start_IT()
+ (++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(),
+ HAL_TIMEx_PWMN_Start_IT()
+ (++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT()
+ (++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(),
+ HAL_TIMEx_HallSensor_Start_IT().
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup TIMEx TIMEx
+ * @brief TIM Extended HAL module driver
+ * @{
+ */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#if defined(TIM_BDTR_BKBID)
+/* Private constants ---------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Constants TIM Extended Private Constants
+ * @{
+ */
+/* Timeout for break input rearm */
+#define TIM_BREAKINPUT_REARM_TIMEOUT 5UL /* 5 milliseconds */
+/**
+ * @}
+ */
+/* End of private constants --------------------------------------------------*/
+
+#endif /* TIM_BDTR_BKBID */
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma);
+static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma);
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions
+ * @{
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions
+ * @brief Timer Hall Sensor functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Timer Hall Sensor functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure TIM HAL Sensor.
+ (+) De-initialize TIM HAL Sensor.
+ (+) Start the Hall Sensor Interface.
+ (+) Stop the Hall Sensor Interface.
+ (+) Start the Hall Sensor Interface and enable interrupts.
+ (+) Stop the Hall Sensor Interface and disable interrupts.
+ (+) Start the Hall Sensor Interface and enable DMA transfers.
+ (+) Stop the Hall Sensor Interface and disable DMA transfers.
+
+@endverbatim
+ * @{
+ */
+/**
+ * @brief Initializes the TIM Hall Sensor Interface and initialize the associated handle.
+ * @note When the timer instance is initialized in Hall Sensor Interface mode,
+ * timer channels 1 and channel 2 are reserved and cannot be used for
+ * other purpose.
+ * @param htim TIM Hall Sensor Interface handle
+ * @param sConfig TIM Hall Sensor configuration structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig)
+{
+ TIM_OC_InitTypeDef OC_Config;
+
+ /* Check the TIM handle allocation */
+ if (htim == NULL)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
+ assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
+ assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
+ assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity));
+ assert_param(IS_TIM_PERIOD(htim, htim->Init.Period));
+ assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
+ assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
+
+ if (htim->State == HAL_TIM_STATE_RESET)
+ {
+ /* Allocate lock resource and initialize it */
+ htim->Lock = HAL_UNLOCKED;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ /* Reset interrupt callbacks to legacy week callbacks */
+ TIM_ResetCallback(htim);
+
+ if (htim->HallSensor_MspInitCallback == NULL)
+ {
+ htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
+ }
+ /* Init the low level hardware : GPIO, CLOCK, NVIC */
+ htim->HallSensor_MspInitCallback(htim);
+#else
+ /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
+ HAL_TIMEx_HallSensor_MspInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+ }
+
+ /* Set the TIM state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Configure the Time base in the Encoder Mode */
+ TIM_Base_SetConfig(htim->Instance, &htim->Init);
+
+ /* Configure the Channel 1 as Input Channel to interface with the three Outputs of the Hall sensor */
+ TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter);
+
+ /* Reset the IC1PSC Bits */
+ htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
+ /* Set the IC1PSC value */
+ htim->Instance->CCMR1 |= sConfig->IC1Prescaler;
+
+ /* Enable the Hall sensor interface (XOR function of the three inputs) */
+ htim->Instance->CR2 |= TIM_CR2_TI1S;
+
+ /* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= TIM_TS_TI1F_ED;
+
+ /* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */
+ htim->Instance->SMCR &= ~TIM_SMCR_SMS;
+ htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
+
+ /* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/
+ OC_Config.OCFastMode = TIM_OCFAST_DISABLE;
+ OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET;
+ OC_Config.OCMode = TIM_OCMODE_PWM2;
+ OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+ OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+ OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH;
+ OC_Config.Pulse = sConfig->Commutation_Delay;
+
+ TIM_OC2_SetConfig(htim->Instance, &OC_Config);
+
+ /* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2
+ register to 101 */
+ htim->Instance->CR2 &= ~TIM_CR2_MMS;
+ htim->Instance->CR2 |= TIM_TRGO_OC2REF;
+
+ /* Initialize the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
+
+ /* Initialize the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Initialize the TIM state*/
+ htim->State = HAL_TIM_STATE_READY;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the TIM Hall Sensor interface
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_INSTANCE(htim->Instance));
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Disable the TIM Peripheral Clock */
+ __HAL_TIM_DISABLE(htim);
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ if (htim->HallSensor_MspDeInitCallback == NULL)
+ {
+ htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
+ }
+ /* DeInit the low level hardware */
+ htim->HallSensor_MspDeInitCallback(htim);
+#else
+ /* DeInit the low level hardware: GPIO, CLOCK, NVIC */
+ HAL_TIMEx_HallSensor_MspDeInit(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ /* Change the DMA burst operation state */
+ htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
+
+ /* Change the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
+
+ /* Change TIM state */
+ htim->State = HAL_TIM_STATE_RESET;
+
+ /* Release Lock */
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the TIM Hall Sensor MSP.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief DeInitializes TIM Hall Sensor MSP.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Starts the TIM Hall Sensor Interface.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim)
+{
+ uint32_t tmpsmcr;
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Check the TIM channels state */
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Input Capture channel 1
+ (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+ TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Hall sensor Interface.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channels 1, 2 and 3
+ (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+ TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Hall Sensor Interface in interrupt mode.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim)
+{
+ uint32_t tmpsmcr;
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Check the TIM channels state */
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the capture compare Interrupts 1 event */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+ /* Enable the Input Capture channel 1
+ (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+ TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Hall Sensor Interface in interrupt mode.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channel 1
+ (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+ TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+ /* Disable the capture compare Interrupts event */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Hall Sensor Interface in DMA mode.
+ * @param htim TIM Hall Sensor Interface handle
+ * @param pData The destination Buffer address.
+ * @param Length The length of data to be transferred from TIM peripheral to memory.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length)
+{
+ uint32_t tmpsmcr;
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Set the TIM channel state */
+ if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
+ || (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
+ {
+ return HAL_BUSY;
+ }
+ else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
+ && (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ /* Enable the Input Capture channel 1
+ (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+ TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
+
+ /* Set the DMA Input Capture 1 Callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
+
+ /* Enable the DMA stream for Capture 1*/
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the capture compare 1 Interrupt */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Hall Sensor Interface in DMA mode.
+ * @param htim TIM Hall Sensor Interface handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
+
+ /* Disable the Input Capture channel 1
+ (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
+ TIM_CHANNEL_2 and TIM_CHANNEL_3) */
+ TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
+
+
+ /* Disable the capture compare Interrupts 1 event */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channel state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions
+ * @brief Timer Complementary Output Compare functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Timer Complementary Output Compare functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Start the Complementary Output Compare/PWM.
+ (+) Stop the Complementary Output Compare/PWM.
+ (+) Start the Complementary Output Compare/PWM and enable interrupts.
+ (+) Stop the Complementary Output Compare/PWM and disable interrupts.
+ (+) Start the Complementary Output Compare/PWM and enable DMA transfers.
+ (+) Stop the Complementary Output Compare/PWM and disable DMA transfers.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the TIM Output Compare signal generation on the complementary
+ * output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Check the TIM complementary channel state */
+ if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation on the complementary
+ * output.
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Disable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in interrupt mode
+ * on the complementary output.
+ * @param htim TIM OC handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Check the TIM complementary channel state */
+ if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Output Compare interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the TIM Break interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in interrupt mode
+ * on the complementary output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpccer;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Output Compare interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Output Compare interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Output Compare interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the TIM Break interrupt (only if no more channel is active) */
+ tmpccer = htim->Instance->CCER;
+ if ((tmpccer & TIM_CCER_CCxNE_MASK) == (uint32_t)RESET)
+ {
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+ }
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Starts the TIM Output Compare signal generation in DMA mode
+ * on the complementary output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+ uint16_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Set the TIM complementary channel state */
+ if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Output Compare DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM Output Compare signal generation in DMA mode
+ * on the complementary output.
+ * @param htim TIM Output Compare handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Output Compare DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Output Compare DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Output Compare DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the Capture compare channel N */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
+ * @brief Timer Complementary PWM functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Timer Complementary PWM functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Start the Complementary PWM.
+ (+) Stop the Complementary PWM.
+ (+) Start the Complementary PWM and enable interrupts.
+ (+) Stop the Complementary PWM and disable interrupts.
+ (+) Start the Complementary PWM and enable DMA transfers.
+ (+) Stop the Complementary PWM and disable DMA transfers.
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the PWM signal generation on the complementary output.
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Check the TIM complementary channel state */
+ if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the PWM signal generation on the complementary output.
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Disable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the PWM signal generation in interrupt mode on the
+ * complementary output.
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Check the TIM complementary channel state */
+ if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Enable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the TIM Break interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
+
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the PWM signal generation in interrupt mode on the
+ * complementary output.
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpccer;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the TIM Break interrupt (only if no more channel is active) */
+ tmpccer = htim->Instance->CCER;
+ if ((tmpccer & TIM_CCER_CCxNE_MASK) == (uint32_t)RESET)
+ {
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
+ }
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Starts the TIM PWM signal generation in DMA mode on the
+ * complementary output
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be enabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @param pData The source Buffer address.
+ * @param Length The length of data to be transferred from memory to TIM peripheral
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
+ uint16_t Length)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ /* Set the TIM complementary channel state */
+ if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
+ {
+ return HAL_BUSY;
+ }
+ else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
+ {
+ if ((pData == NULL) || (Length == 0U))
+ {
+ return HAL_ERROR;
+ }
+ else
+ {
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
+ }
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+ htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+ htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Set the DMA compare callbacks */
+ htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
+ htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
+
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
+
+ /* Enable the DMA stream */
+ if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
+ Length) != HAL_OK)
+ {
+ /* Return error status */
+ return HAL_ERROR;
+ }
+ /* Enable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Enable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
+ if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+ else
+ {
+ __HAL_TIM_ENABLE(htim);
+ }
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @brief Stops the TIM PWM signal generation in DMA mode on the complementary
+ * output
+ * @param htim TIM handle
+ * @param Channel TIM Channel to be disabled
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ {
+ /* Disable the TIM Capture/Compare 1 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
+ break;
+ }
+
+ case TIM_CHANNEL_2:
+ {
+ /* Disable the TIM Capture/Compare 2 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
+ break;
+ }
+
+ case TIM_CHANNEL_3:
+ {
+ /* Disable the TIM Capture/Compare 3 DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
+ (void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
+ break;
+ }
+
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ if (status == HAL_OK)
+ {
+ /* Disable the complementary PWM output */
+ TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM complementary channel state */
+ TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
+ }
+
+ /* Return function status */
+ return status;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
+ * @brief Timer Complementary One Pulse functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Timer Complementary One Pulse functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Start the Complementary One Pulse generation.
+ (+) Stop the Complementary One Pulse.
+ (+) Start the Complementary One Pulse and enable interrupts.
+ (+) Stop the Complementary One Pulse and disable interrupts.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Starts the TIM One Pulse signal generation on the complementary
+ * output.
+ * @note OutputChannel must match the pulse output channel chosen when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel pulse output channel to enable
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Check the TIM channels state */
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the complementary One Pulse output channel and the Input Capture channel */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation on the complementary
+ * output.
+ * @note OutputChannel must match the pulse output channel chosen when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel pulse output channel to disable
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Disable the complementary One Pulse output channel and the Input Capture channel */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Starts the TIM One Pulse signal generation in interrupt mode on the
+ * complementary channel.
+ * @note OutputChannel must match the pulse output channel chosen when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel pulse output channel to enable
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+ HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
+ HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Check the TIM channels state */
+ if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
+ || (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
+
+ /* Enable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
+
+ /* Enable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
+
+ /* Enable the complementary One Pulse output channel and the Input Capture channel */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
+ TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
+
+ /* Enable the Main Output */
+ __HAL_TIM_MOE_ENABLE(htim);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @brief Stops the TIM One Pulse signal generation in interrupt mode on the
+ * complementary channel.
+ * @note OutputChannel must match the pulse output channel chosen when calling
+ * @ref HAL_TIM_OnePulse_ConfigChannel().
+ * @param htim TIM One Pulse handle
+ * @param OutputChannel pulse output channel to disable
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
+{
+ uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
+
+ /* Disable the TIM Capture/Compare 1 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
+
+ /* Disable the TIM Capture/Compare 2 interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
+
+ /* Disable the complementary One Pulse output channel and the Input Capture channel */
+ TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
+ TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
+
+ /* Disable the Main Output */
+ __HAL_TIM_MOE_DISABLE(htim);
+
+ /* Disable the Peripheral */
+ __HAL_TIM_DISABLE(htim);
+
+ /* Set the TIM channels state */
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+
+ /* Return function status */
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
+ * @brief Peripheral Control functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Peripheral Control functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Configure the commutation event in case of use of the Hall sensor interface.
+ (+) Configure Output channels for OC and PWM mode.
+
+ (+) Configure Complementary channels, break features and dead time.
+ (+) Configure Master synchronization.
+ (+) Configure timer remapping capabilities.
+ (+) Select timer input source.
+ (+) Enable or disable channel grouping.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Configure the TIM commutation event sequence.
+ * @note This function is mandatory to use the commutation event in order to
+ * update the configuration at each commutation detection on the TRGI input of the Timer,
+ * the typical use of this feature is with the use of another Timer(interface Timer)
+ * configured in Hall sensor interface, this interface Timer will generate the
+ * commutation at its TRGO output (connected to Timer used in this function) each time
+ * the TI1 of the Interface Timer detect a commutation at its input TI1.
+ * @param htim TIM handle
+ * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+ * This parameter can be one of the following values:
+ * @arg TIM_TS_ITR0: Internal trigger 0 selected
+ * @arg TIM_TS_ITR1: Internal trigger 1 selected
+ * @arg TIM_TS_ITR2: Internal trigger 2 selected
+ * @arg TIM_TS_ITR3: Internal trigger 3 selected
+ * @arg TIM_TS_ITR12: Internal trigger 12 selected (*)
+ * @arg TIM_TS_ITR13: Internal trigger 13 selected (*)
+ * @arg TIM_TS_NONE: No trigger is needed
+ *
+ * (*) Value not defined in all devices.
+ *
+ * @param CommutationSource the Commutation Event source
+ * This parameter can be one of the following values:
+ * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+ * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
+ uint32_t CommutationSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+ __HAL_LOCK(htim);
+
+ if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+ (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3) ||
+ (InputTrigger == TIM_TS_ITR12) || (InputTrigger == TIM_TS_ITR13))
+ {
+ /* Select the Input trigger */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= InputTrigger;
+ }
+
+ /* Select the Capture Compare preload feature */
+ htim->Instance->CR2 |= TIM_CR2_CCPC;
+ /* Select the Commutation event source */
+ htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+ htim->Instance->CR2 |= CommutationSource;
+
+ /* Disable Commutation Interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
+
+ /* Disable Commutation DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the TIM commutation event sequence with interrupt.
+ * @note This function is mandatory to use the commutation event in order to
+ * update the configuration at each commutation detection on the TRGI input of the Timer,
+ * the typical use of this feature is with the use of another Timer(interface Timer)
+ * configured in Hall sensor interface, this interface Timer will generate the
+ * commutation at its TRGO output (connected to Timer used in this function) each time
+ * the TI1 of the Interface Timer detect a commutation at its input TI1.
+ * @param htim TIM handle
+ * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+ * This parameter can be one of the following values:
+ * @arg TIM_TS_ITR0: Internal trigger 0 selected
+ * @arg TIM_TS_ITR1: Internal trigger 1 selected
+ * @arg TIM_TS_ITR2: Internal trigger 2 selected
+ * @arg TIM_TS_ITR3: Internal trigger 3 selected
+ * @arg TIM_TS_ITR12: Internal trigger 12 selected (*)
+ * @arg TIM_TS_ITR13: Internal trigger 13 selected (*)
+ * @arg TIM_TS_NONE: No trigger is needed
+ *
+ * (*) Value not defined in all devices.
+ *
+ * @param CommutationSource the Commutation Event source
+ * This parameter can be one of the following values:
+ * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+ * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
+ uint32_t CommutationSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+ __HAL_LOCK(htim);
+
+ if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+ (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3) ||
+ (InputTrigger == TIM_TS_ITR12) || (InputTrigger == TIM_TS_ITR13))
+ {
+ /* Select the Input trigger */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= InputTrigger;
+ }
+
+ /* Select the Capture Compare preload feature */
+ htim->Instance->CR2 |= TIM_CR2_CCPC;
+ /* Select the Commutation event source */
+ htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+ htim->Instance->CR2 |= CommutationSource;
+
+ /* Disable Commutation DMA request */
+ __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
+
+ /* Enable the Commutation Interrupt */
+ __HAL_TIM_ENABLE_IT(htim, TIM_IT_COM);
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the TIM commutation event sequence with DMA.
+ * @note This function is mandatory to use the commutation event in order to
+ * update the configuration at each commutation detection on the TRGI input of the Timer,
+ * the typical use of this feature is with the use of another Timer(interface Timer)
+ * configured in Hall sensor interface, this interface Timer will generate the
+ * commutation at its TRGO output (connected to Timer used in this function) each time
+ * the TI1 of the Interface Timer detect a commutation at its input TI1.
+ * @note The user should configure the DMA in his own software, in This function only the COMDE bit is set
+ * @param htim TIM handle
+ * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
+ * This parameter can be one of the following values:
+ * @arg TIM_TS_ITR0: Internal trigger 0 selected
+ * @arg TIM_TS_ITR1: Internal trigger 1 selected
+ * @arg TIM_TS_ITR2: Internal trigger 2 selected
+ * @arg TIM_TS_ITR3: Internal trigger 3 selected
+ * @arg TIM_TS_ITR12: Internal trigger 12 selected (*)
+ * @arg TIM_TS_ITR13: Internal trigger 13 selected (*)
+ * @arg TIM_TS_NONE: No trigger is needed
+ *
+ * (*) Value not defined in all devices.
+ *
+ * @param CommutationSource the Commutation Event source
+ * This parameter can be one of the following values:
+ * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
+ * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
+ uint32_t CommutationSource)
+{
+ /* Check the parameters */
+ assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
+
+ __HAL_LOCK(htim);
+
+ if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
+ (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3) ||
+ (InputTrigger == TIM_TS_ITR12) || (InputTrigger == TIM_TS_ITR13))
+ {
+ /* Select the Input trigger */
+ htim->Instance->SMCR &= ~TIM_SMCR_TS;
+ htim->Instance->SMCR |= InputTrigger;
+ }
+
+ /* Select the Capture Compare preload feature */
+ htim->Instance->CR2 |= TIM_CR2_CCPC;
+ /* Select the Commutation event source */
+ htim->Instance->CR2 &= ~TIM_CR2_CCUS;
+ htim->Instance->CR2 |= CommutationSource;
+
+ /* Enable the Commutation DMA Request */
+ /* Set the DMA Commutation Callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
+ /* Set the DMA error callback */
+ htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError;
+
+ /* Disable Commutation Interrupt */
+ __HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
+
+ /* Enable the Commutation DMA Request */
+ __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM);
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the TIM in master mode.
+ * @param htim TIM handle.
+ * @param sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that
+ * contains the selected trigger output (TRGO) and the Master/Slave
+ * mode.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
+ const TIM_MasterConfigTypeDef *sMasterConfig)
+{
+ uint32_t tmpcr2;
+ uint32_t tmpsmcr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_MASTER_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
+ assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ /* Change the handler state */
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Get the TIMx CR2 register value */
+ tmpcr2 = htim->Instance->CR2;
+
+ /* Get the TIMx SMCR register value */
+ tmpsmcr = htim->Instance->SMCR;
+
+ /* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */
+ if (IS_TIM_TRGO2_INSTANCE(htim->Instance))
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_TRGO2_SOURCE(sMasterConfig->MasterOutputTrigger2));
+
+ /* Clear the MMS2 bits */
+ tmpcr2 &= ~TIM_CR2_MMS2;
+ /* Select the TRGO2 source*/
+ tmpcr2 |= sMasterConfig->MasterOutputTrigger2;
+ }
+
+ /* Reset the MMS Bits */
+ tmpcr2 &= ~TIM_CR2_MMS;
+ /* Select the TRGO source */
+ tmpcr2 |= sMasterConfig->MasterOutputTrigger;
+
+ /* Update TIMx CR2 */
+ htim->Instance->CR2 = tmpcr2;
+
+ if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
+ {
+ /* Reset the MSM Bit */
+ tmpsmcr &= ~TIM_SMCR_MSM;
+ /* Set master mode */
+ tmpsmcr |= sMasterConfig->MasterSlaveMode;
+
+ /* Update TIMx SMCR */
+ htim->Instance->SMCR = tmpsmcr;
+ }
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Configures the Break feature, dead time, Lock level, OSSI/OSSR State
+ * and the AOE(automatic output enable).
+ * @param htim TIM handle
+ * @param sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that
+ * contains the BDTR Register configuration information for the TIM peripheral.
+ * @note Interrupts can be generated when an active level is detected on the
+ * break input, the break 2 input or the system break input. Break
+ * interrupt can be enabled by calling the @ref __HAL_TIM_ENABLE_IT macro.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
+ const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig)
+{
+ /* Keep this variable initialized to 0 as it is used to configure BDTR register */
+ uint32_t tmpbdtr = 0U;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode));
+ assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode));
+ assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel));
+ assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime));
+ assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState));
+ assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity));
+ assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->BreakFilter));
+ assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput));
+#if defined(TIM_BDTR_BKBID)
+ assert_param(IS_TIM_BREAK_AFMODE(sBreakDeadTimeConfig->BreakAFMode));
+#endif /* TIM_BDTR_BKBID */
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
+ the OSSI State, the dead time value and the Automatic Output Enable Bit */
+
+ /* Set the BDTR bits */
+ MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (sBreakDeadTimeConfig->BreakFilter << TIM_BDTR_BKF_Pos));
+#if defined(TIM_BDTR_BKBID)
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BKBID, sBreakDeadTimeConfig->BreakAFMode);
+#endif /* TIM_BDTR_BKBID */
+
+ if (IS_TIM_BKIN2_INSTANCE(htim->Instance))
+ {
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State));
+ assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity));
+ assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter));
+#if defined(TIM_BDTR_BKBID)
+ assert_param(IS_TIM_BREAK2_AFMODE(sBreakDeadTimeConfig->Break2AFMode));
+#endif /* TIM_BDTR_BKBID */
+
+ /* Set the BREAK2 input related BDTR bits */
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (sBreakDeadTimeConfig->Break2Filter << TIM_BDTR_BK2F_Pos));
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, sBreakDeadTimeConfig->Break2State);
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, sBreakDeadTimeConfig->Break2Polarity);
+#if defined(TIM_BDTR_BKBID)
+ MODIFY_REG(tmpbdtr, TIM_BDTR_BK2BID, sBreakDeadTimeConfig->Break2AFMode);
+#endif /* TIM_BDTR_BKBID */
+ }
+
+ /* Set TIMx_BDTR */
+ htim->Instance->BDTR = tmpbdtr;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+#if defined(TIM_BREAK_INPUT_SUPPORT)
+
+/**
+ * @brief Configures the break input source.
+ * @param htim TIM handle.
+ * @param BreakInput Break input to configure
+ * This parameter can be one of the following values:
+ * @arg TIM_BREAKINPUT_BRK: Timer break input
+ * @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
+ * @param sBreakInputConfig Break input source configuration
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim,
+ uint32_t BreakInput,
+ const TIMEx_BreakInputConfigTypeDef *sBreakInputConfig)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmporx;
+ uint32_t bkin_enable_mask;
+ uint32_t bkin_polarity_mask;
+ uint32_t bkin_enable_bitpos;
+ uint32_t bkin_polarity_bitpos;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_BREAKINPUT(BreakInput));
+ assert_param(IS_TIM_BREAKINPUTSOURCE(sBreakInputConfig->Source));
+ assert_param(IS_TIM_BREAKINPUTSOURCE_STATE(sBreakInputConfig->Enable));
+ if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1)
+ {
+ assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity));
+ }
+
+ /* Check input state */
+ __HAL_LOCK(htim);
+
+ switch (sBreakInputConfig->Source)
+ {
+ case TIM_BREAKINPUTSOURCE_BKIN:
+ {
+ bkin_enable_mask = TIM1_AF1_BKINE;
+ bkin_enable_bitpos = TIM1_AF1_BKINE_Pos;
+ bkin_polarity_mask = TIM1_AF1_BKINP;
+ bkin_polarity_bitpos = TIM1_AF1_BKINP_Pos;
+ break;
+ }
+ case TIM_BREAKINPUTSOURCE_COMP1:
+ {
+ bkin_enable_mask = TIM1_AF1_BKCMP1E;
+ bkin_enable_bitpos = TIM1_AF1_BKCMP1E_Pos;
+ bkin_polarity_mask = TIM1_AF1_BKCMP1P;
+ bkin_polarity_bitpos = TIM1_AF1_BKCMP1P_Pos;
+ break;
+ }
+ case TIM_BREAKINPUTSOURCE_COMP2:
+ {
+ bkin_enable_mask = TIM1_AF1_BKCMP2E;
+ bkin_enable_bitpos = TIM1_AF1_BKCMP2E_Pos;
+ bkin_polarity_mask = TIM1_AF1_BKCMP2P;
+ bkin_polarity_bitpos = TIM1_AF1_BKCMP2P_Pos;
+ break;
+ }
+ case TIM_BREAKINPUTSOURCE_DFSDM1:
+ {
+ bkin_enable_mask = TIM1_AF1_BKDF1BK0E;
+ bkin_enable_bitpos = TIM1_AF1_BKDF1BK0E_Pos;
+ bkin_polarity_mask = 0U;
+ bkin_polarity_bitpos = 0U;
+ break;
+ }
+
+ default:
+ {
+ bkin_enable_mask = 0U;
+ bkin_polarity_mask = 0U;
+ bkin_enable_bitpos = 0U;
+ bkin_polarity_bitpos = 0U;
+ break;
+ }
+ }
+
+ switch (BreakInput)
+ {
+ case TIM_BREAKINPUT_BRK:
+ {
+ /* Get the TIMx_AF1 register value */
+ tmporx = htim->Instance->AF1;
+
+ /* Enable the break input */
+ tmporx &= ~bkin_enable_mask;
+ tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
+
+ /* Set the break input polarity */
+ if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1)
+ {
+ tmporx &= ~bkin_polarity_mask;
+ tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
+ }
+
+ /* Set TIMx_AF1 */
+ htim->Instance->AF1 = tmporx;
+ break;
+ }
+ case TIM_BREAKINPUT_BRK2:
+ {
+ /* Get the TIMx_AF2 register value */
+ tmporx = htim->Instance->AF2;
+
+ /* Enable the break input */
+ tmporx &= ~bkin_enable_mask;
+ tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
+
+ /* Set the break input polarity */
+ if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1)
+ {
+ tmporx &= ~bkin_polarity_mask;
+ tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
+ }
+
+ /* Set TIMx_AF2 */
+ htim->Instance->AF2 = tmporx;
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+#endif /*TIM_BREAK_INPUT_SUPPORT */
+
+/**
+ * @brief Configures the TIMx Remapping input capabilities.
+ * @param htim TIM handle.
+ * @param Remap specifies the TIM remapping source.
+ * For TIM1, the parameter is one of the following values:
+ * @arg TIM_TIM1_ETR_GPIO: TIM1_ETR is connected to GPIO
+ * @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output
+ * @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output
+ * @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1
+ * @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2
+ * @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3
+ * @arg TIM_TIM1_ETR_ADC3_AWD1: TIM1_ETR is connected to ADC3 AWD1
+ * @arg TIM_TIM1_ETR_ADC3_AWD2: TIM1_ETR is connected to ADC3 AWD2
+ * @arg TIM_TIM1_ETR_ADC3_AWD3: TIM1_ETR is connected to ADC3 AWD3
+ *
+ * For TIM2, the parameter is one of the following values:
+ * @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO
+ * @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output
+ * @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output
+ * @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE
+ * @arg TIM_TIM2_ETR_SAI1_FSA: TIM2_ETR is connected to SAI1 FS_A
+ * @arg TIM_TIM2_ETR_SAI1_FSB: TIM2_ETR is connected to SAI1 FS_B
+ *
+ * For TIM3, the parameter is one of the following values:
+ * @arg TIM_TIM3_ETR_GPIO: TIM3_ETR is connected to GPIO
+ * @arg TIM_TIM3_ETR_COMP1: TIM3_ETR is connected to COMP1 output
+ *
+ * For TIM5, the parameter is one of the following values:
+ * @arg TIM_TIM5_ETR_GPIO: TIM5_ETR is connected to GPIO
+ * @arg TIM_TIM5_ETR_SAI2_FSA: TIM5_ETR is connected to SAI2 FS_A (*)
+ * @arg TIM_TIM5_ETR_SAI2_FSB: TIM5_ETR is connected to SAI2 FS_B (*)
+ * @arg TIM_TIM5_ETR_SAI4_FSA: TIM5_ETR is connected to SAI2 FS_A (*)
+ * @arg TIM_TIM5_ETR_SAI4_FSB: TIM5_ETR is connected to SAI2 FS_B (*)
+ *
+ * For TIM8, the parameter is one of the following values:
+ * @arg TIM_TIM8_ETR_GPIO: TIM8_ETR is connected to GPIO
+ * @arg TIM_TIM8_ETR_COMP1: TIM8_ETR is connected to COMP1 output
+ * @arg TIM_TIM8_ETR_COMP2: TIM8_ETR is connected to COMP2 output
+ * @arg TIM_TIM8_ETR_ADC2_AWD1: TIM8_ETR is connected to ADC2 AWD1
+ * @arg TIM_TIM8_ETR_ADC2_AWD2: TIM8_ETR is connected to ADC2 AWD2
+ * @arg TIM_TIM8_ETR_ADC2_AWD3: TIM8_ETR is connected to ADC2 AWD3
+ * @arg TIM_TIM8_ETR_ADC3_AWD1: TIM8_ETR is connected to ADC3 AWD1
+ * @arg TIM_TIM8_ETR_ADC3_AWD2: TIM8_ETR is connected to ADC3 AWD2
+ * @arg TIM_TIM8_ETR_ADC3_AWD3: TIM8_ETR is connected to ADC3 AWD3
+ *
+ * For TIM23, the parameter is one of the following values: (*)
+ * @arg TIM_TIM23_ETR_GPIO TIM23_ETR is connected to GPIO
+ * @arg TIM_TIM23_ETR_COMP1 TIM23_ETR is connected to COMP1 output
+ * @arg TIM_TIM23_ETR_COMP2 TIM23_ETR is connected to COMP2 output
+ *
+ * For TIM24, the parameter is one of the following values: (*)
+ * @arg TIM_TIM24_ETR_GPIO TIM24_ETR is connected to GPIO
+ * @arg TIM_TIM24_ETR_SAI4_FSA TIM24_ETR is connected to SAI4 FS_A
+ * @arg TIM_TIM24_ETR_SAI4_FSB TIM24_ETR is connected to SAI4 FS_B
+ * @arg TIM_TIM24_ETR_SAI1_FSA TIM24_ETR is connected to SAI1 FS_A
+ * @arg TIM_TIM24_ETR_SAI1_FSB TIM24_ETR is connected to SAI1 FS_B
+ *
+ * (*) Value not defined in all devices.
+ *
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
+{
+ /* Check parameters */
+ assert_param(IS_TIM_REMAP_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_REMAP(Remap));
+
+ __HAL_LOCK(htim);
+
+ MODIFY_REG(htim->Instance->AF1, TIM1_AF1_ETRSEL_Msk, Remap);
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Select the timer input source
+ * @param htim TIM handle.
+ * @param Channel specifies the TIM Channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TI1 input channel
+ * @arg TIM_CHANNEL_2: TI2 input channel
+ * @arg TIM_CHANNEL_3: TIM Channel 3
+ * @arg TIM_CHANNEL_4: TIM Channel 4
+ * @param TISelection parameter of the TIM_TISelectionStruct structure is detailed as follows:
+ * For TIM1, the parameter is one of the following values:
+ * @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO
+ * @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output
+ *
+ * For TIM2, the parameter is one of the following values:
+ * @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO
+ * @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output
+ * @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output
+ * @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output
+ *
+ * For TIM3, the parameter is one of the following values:
+ * @arg TIM_TIM3_TI1_GPIO: TIM3 TI1 is connected to GPIO
+ * @arg TIM_TIM3_TI1_COMP1: TIM3 TI1 is connected to COMP1 output
+ * @arg TIM_TIM3_TI1_COMP2: TIM3 TI1 is connected to COMP2 output
+ * @arg TIM_TIM3_TI1_COMP1_COMP2: TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output
+ *
+ * For TIM5, the parameter is one of the following values:
+ * @arg TIM_TIM5_TI1_GPIO: TIM5 TI1 is connected to GPIO
+ * @arg TIM_TIM5_TI1_CAN_TMP: TIM5 TI1 is connected to CAN TMP
+ * @arg TIM_TIM5_TI1_CAN_RTP: TIM5 TI1 is connected to CAN RTP
+ *
+ * For TIM8, the parameter is one of the following values:
+ * @arg TIM_TIM8_TI1_GPIO: TIM8 TI1 is connected to GPIO
+ * @arg TIM_TIM8_TI1_COMP2: TIM8 TI1 is connected to COMP2 output
+ *
+ * For TIM12, the parameter can have the following values: (*)
+ * @arg TIM_TIM12_TI1_GPIO: TIM12 TI1 is connected to GPIO
+ * @arg TIM_TIM12_TI1_SPDIF_FS: TIM12 TI1 is connected to SPDIF FS
+ *
+ * For TIM15, the parameter is one of the following values:
+ * @arg TIM_TIM15_TI1_GPIO: TIM15 TI1 is connected to GPIO
+ * @arg TIM_TIM15_TI1_TIM2_CH1: TIM15 TI1 is connected to TIM2 CH1
+ * @arg TIM_TIM15_TI1_TIM3_CH1: TIM15 TI1 is connected to TIM3 CH1
+ * @arg TIM_TIM15_TI1_TIM4_CH1: TIM15 TI1 is connected to TIM4 CH1
+ * @arg TIM_TIM15_TI1_RCC_LSE: TIM15 TI1 is connected to LSE
+ * @arg TIM_TIM15_TI1_RCC_CSI: TIM15 TI1 is connected to CSI
+ * @arg TIM_TIM15_TI1_RCC_MCO2: TIM15 TI1 is connected to MCO2
+ * @arg TIM_TIM15_TI2_GPIO: TIM15 TI2 is connected to GPIO
+ * @arg TIM_TIM15_TI2_TIM2_CH2: TIM15 TI2 is connected to TIM2 CH2
+ * @arg TIM_TIM15_TI2_TIM3_CH2: TIM15 TI2 is connected to TIM3 CH2
+ * @arg TIM_TIM15_TI2_TIM4_CH2: TIM15 TI2 is connected to TIM4 CH2
+ *
+ * For TIM16, the parameter can have the following values:
+ * @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO
+ * @arg TIM_TIM16_TI1_RCC_LSI: TIM16 TI1 is connected to LSI
+ * @arg TIM_TIM16_TI1_RCC_LSE: TIM16 TI1 is connected to LSE
+ * @arg TIM_TIM16_TI1_WKUP_IT: TIM16 TI1 is connected to RTC wakeup interrupt
+ *
+ * For TIM17, the parameter can have the following values:
+ * @arg TIM_TIM17_TI1_GPIO: TIM17 TI1 is connected to GPIO
+ * @arg TIM_TIM17_TI1_SPDIF_FS: TIM17 TI1 is connected to SPDIF FS (*)
+ * @arg TIM_TIM17_TI1_RCC_HSE1MHZ: TIM17 TI1 is connected to HSE 1MHz
+ * @arg TIM_TIM17_TI1_RCC_MCO1: TIM17 TI1 is connected to MCO1
+ *
+ * For TIM23, the parameter can have the following values: (*)
+ * @arg TIM_TIM23_TI4_GPIO TIM23_TI4 is connected to GPIO
+ * @arg TIM_TIM23_TI4_COMP1 TIM23_TI4 is connected to COMP1 output
+ * @arg TIM_TIM23_TI4_COMP2 TIM23_TI4 is connected to COMP2 output
+ * @arg TIM_TIM23_TI4_COMP1_COMP2 TIM23_TI4 is connected to COMP2 output
+ *
+ * For TIM24, the parameter can have the following values: (*)
+ * @arg TIM_TIM24_TI1_GPIO TIM24_TI1 is connected to GPIO
+ * @arg TIM_TIM24_TI1_CAN_TMP TIM24_TI1 is connected to CAN_TMP
+ * @arg TIM_TIM24_TI1_CAN_RTP TIM24_TI1 is connected to CAN_RTP
+ * @arg TIM_TIM24_TI1_CAN_SOC TIM24_TI1 is connected to CAN_SOC
+ *
+ * (*) Value not defined in all devices. \n
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_TISelection(TIM_HandleTypeDef *htim, uint32_t TISelection, uint32_t Channel)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+
+ /* Check parameters */
+ assert_param(IS_TIM_TISEL_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_TISEL(TISelection));
+
+ __HAL_LOCK(htim);
+
+ switch (Channel)
+ {
+ case TIM_CHANNEL_1:
+ MODIFY_REG(htim->Instance->TISEL, TIM_TISEL_TI1SEL, TISelection);
+ break;
+ case TIM_CHANNEL_2:
+ MODIFY_REG(htim->Instance->TISEL, TIM_TISEL_TI2SEL, TISelection);
+ break;
+ case TIM_CHANNEL_3:
+ MODIFY_REG(htim->Instance->TISEL, TIM_TISEL_TI3SEL, TISelection);
+ break;
+ case TIM_CHANNEL_4:
+ MODIFY_REG(htim->Instance->TISEL, TIM_TISEL_TI4SEL, TISelection);
+ break;
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ __HAL_UNLOCK(htim);
+
+ return status;
+}
+
+/**
+ * @brief Group channel 5 and channel 1, 2 or 3
+ * @param htim TIM handle.
+ * @param Channels specifies the reference signal(s) the OC5REF is combined with.
+ * This parameter can be any combination of the following values:
+ * TIM_GROUPCH5_NONE: No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC
+ * TIM_GROUPCH5_OC1REFC: OC1REFC is the logical AND of OC1REFC and OC5REF
+ * TIM_GROUPCH5_OC2REFC: OC2REFC is the logical AND of OC2REFC and OC5REF
+ * TIM_GROUPCH5_OC3REFC: OC3REFC is the logical AND of OC3REFC and OC5REF
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels)
+{
+ /* Check parameters */
+ assert_param(IS_TIM_COMBINED3PHASEPWM_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_GROUPCH5(Channels));
+
+ /* Process Locked */
+ __HAL_LOCK(htim);
+
+ htim->State = HAL_TIM_STATE_BUSY;
+
+ /* Clear GC5Cx bit fields */
+ htim->Instance->CCR5 &= ~(TIM_CCR5_GC5C3 | TIM_CCR5_GC5C2 | TIM_CCR5_GC5C1);
+
+ /* Set GC5Cx bit fields */
+ htim->Instance->CCR5 |= Channels;
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+ __HAL_UNLOCK(htim);
+
+ return HAL_OK;
+}
+#if defined(TIM_BDTR_BKBID)
+
+/**
+ * @brief Disarm the designated break input (when it operates in bidirectional mode).
+ * @param htim TIM handle.
+ * @param BreakInput Break input to disarm
+ * This parameter can be one of the following values:
+ * @arg TIM_BREAKINPUT_BRK: Timer break input
+ * @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
+ * @note The break input can be disarmed only when it is configured in
+ * bidirectional mode and when when MOE is reset.
+ * @note Purpose is to be able to have the input voltage back to high-state,
+ * whatever the time constant on the output .
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_DisarmBreakInput(TIM_HandleTypeDef *htim, uint32_t BreakInput)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tmpbdtr;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_BREAKINPUT(BreakInput));
+
+ switch (BreakInput)
+ {
+ case TIM_BREAKINPUT_BRK:
+ {
+ /* Check initial conditions */
+ tmpbdtr = READ_REG(htim->Instance->BDTR);
+ if ((READ_BIT(tmpbdtr, TIM_BDTR_BKBID) == TIM_BDTR_BKBID) &&
+ (READ_BIT(tmpbdtr, TIM_BDTR_MOE) == 0U))
+ {
+ /* Break input BRK is disarmed */
+ SET_BIT(htim->Instance->BDTR, TIM_BDTR_BKDSRM);
+ }
+ break;
+ }
+ case TIM_BREAKINPUT_BRK2:
+ {
+ /* Check initial conditions */
+ tmpbdtr = READ_REG(htim->Instance->BDTR);
+ if ((READ_BIT(tmpbdtr, TIM_BDTR_BK2BID) == TIM_BDTR_BK2BID) &&
+ (READ_BIT(tmpbdtr, TIM_BDTR_MOE) == 0U))
+ {
+ /* Break input BRK is disarmed */
+ SET_BIT(htim->Instance->BDTR, TIM_BDTR_BK2DSRM);
+ }
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief Arm the designated break input (when it operates in bidirectional mode).
+ * @param htim TIM handle.
+ * @param BreakInput Break input to arm
+ * This parameter can be one of the following values:
+ * @arg TIM_BREAKINPUT_BRK: Timer break input
+ * @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
+ * @note Arming is possible at anytime, even if fault is present.
+ * @note Break input is automatically armed as soon as MOE bit is set.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_TIMEx_ReArmBreakInput(const TIM_HandleTypeDef *htim, uint32_t BreakInput)
+{
+ HAL_StatusTypeDef status = HAL_OK;
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
+ assert_param(IS_TIM_BREAKINPUT(BreakInput));
+
+ switch (BreakInput)
+ {
+ case TIM_BREAKINPUT_BRK:
+ {
+ /* Check initial conditions */
+ if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BKBID) == TIM_BDTR_BKBID)
+ {
+ /* Break input BRK is re-armed automatically by hardware. Poll to check whether fault condition disappeared */
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+ while (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BKDSRM) != 0UL)
+ {
+ if ((HAL_GetTick() - tickstart) > TIM_BREAKINPUT_REARM_TIMEOUT)
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BKDSRM) != 0UL)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case TIM_BREAKINPUT_BRK2:
+ {
+ /* Check initial conditions */
+ if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BK2BID) == TIM_BDTR_BK2BID)
+ {
+ /* Break input BRK2 is re-armed automatically by hardware. Poll to check whether fault condition disappeared */
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+ while (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BK2DSRM) != 0UL)
+ {
+ if ((HAL_GetTick() - tickstart) > TIM_BREAKINPUT_REARM_TIMEOUT)
+ {
+ /* New check to avoid false timeout detection in case of preemption */
+ if (READ_BIT(htim->Instance->BDTR, TIM_BDTR_BK2DSRM) != 0UL)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ status = HAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+#endif /* TIM_BDTR_BKBID */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
+ * @brief Extended Callbacks functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended Callbacks functions #####
+ ==============================================================================
+ [..]
+ This section provides Extended TIM callback functions:
+ (+) Timer Commutation callback
+ (+) Timer Break callback
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Commutation callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_CommutCallback could be implemented in the user file
+ */
+}
+/**
+ * @brief Commutation half complete callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_CommutHalfCpltCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Break detection callback in non-blocking mode
+ * @param htim TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function should not be modified, when the callback is needed,
+ the HAL_TIMEx_BreakCallback could be implemented in the user file
+ */
+}
+
+/**
+ * @brief Break2 detection callback in non blocking mode
+ * @param htim: TIM handle
+ * @retval None
+ */
+__weak void HAL_TIMEx_Break2Callback(TIM_HandleTypeDef *htim)
+{
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(htim);
+
+ /* NOTE : This function Should not be modified, when the callback is needed,
+ the HAL_TIMEx_Break2Callback could be implemented in the user file
+ */
+}
+/**
+ * @}
+ */
+
+/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
+ * @brief Extended Peripheral State functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Extended Peripheral State functions #####
+ ==============================================================================
+ [..]
+ This subsection permits to get in run-time the status of the peripheral
+ and the data flow.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Return the TIM Hall Sensor interface handle state.
+ * @param htim TIM Hall Sensor handle
+ * @retval HAL state
+ */
+HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim)
+{
+ return htim->State;
+}
+
+/**
+ * @brief Return actual state of the TIM complementary channel.
+ * @param htim TIM handle
+ * @param ChannelN TIM Complementary channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @retval TIM Complementary channel state
+ */
+HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim, uint32_t ChannelN)
+{
+ HAL_TIM_ChannelStateTypeDef channel_state;
+
+ /* Check the parameters */
+ assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, ChannelN));
+
+ channel_state = TIM_CHANNEL_N_STATE_GET(htim, ChannelN);
+
+ return channel_state;
+}
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/* Private functions ---------------------------------------------------------*/
+/** @defgroup TIMEx_Private_Functions TIM Extended Private Functions
+ * @{
+ */
+
+/**
+ * @brief TIM DMA Commutation callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->CommutationCallback(htim);
+#else
+ HAL_TIMEx_CommutCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+/**
+ * @brief TIM DMA Commutation half complete callback.
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ /* Change the htim state */
+ htim->State = HAL_TIM_STATE_READY;
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->CommutationHalfCpltCallback(htim);
+#else
+ HAL_TIMEx_CommutHalfCpltCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+}
+
+
+/**
+ * @brief TIM DMA Delay Pulse complete callback (complementary channel).
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+
+ if (hdma->Init.Mode == DMA_NORMAL)
+ {
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->PWM_PulseFinishedCallback(htim);
+#else
+ HAL_TIM_PWM_PulseFinishedCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief TIM DMA error callback (complementary channel)
+ * @param hdma pointer to DMA handle.
+ * @retval None
+ */
+static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma)
+{
+ TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
+
+ if (hdma == htim->hdma[TIM_DMA_ID_CC1])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
+ {
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
+ TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
+ }
+ else
+ {
+ /* nothing to do */
+ }
+
+#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
+ htim->ErrorCallback(htim);
+#else
+ HAL_TIM_ErrorCallback(htim);
+#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
+
+ htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
+}
+
+/**
+ * @brief Enables or disables the TIM Capture Compare Channel xN.
+ * @param TIMx to select the TIM peripheral
+ * @param Channel specifies the TIM Channel
+ * This parameter can be one of the following values:
+ * @arg TIM_CHANNEL_1: TIM Channel 1 selected
+ * @arg TIM_CHANNEL_2: TIM Channel 2 selected
+ * @arg TIM_CHANNEL_3: TIM Channel 3 selected
+ * @param ChannelNState specifies the TIM Channel CCxNE bit new state.
+ * This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable.
+ * @retval None
+ */
+static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState)
+{
+ uint32_t tmp;
+
+ tmp = TIM_CCER_CC1NE << (Channel & 0xFU); /* 0xFU = 15 bits max shift */
+
+ /* Reset the CCxNE Bit */
+ TIMx->CCER &= ~tmp;
+
+ /* Set or reset the CCxNE Bit */
+ TIMx->CCER |= (uint32_t)(ChannelNState << (Channel & 0xFU)); /* 0xFU = 15 bits max shift */
+}
+/**
+ * @}
+ */
+
+#endif /* HAL_TIM_MODULE_ENABLED */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_delayblock.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_delayblock.c
new file mode 100755
index 0000000..d7ac9bc
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_delayblock.c
@@ -0,0 +1,214 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_delayblock.c
+ * @author MCD Application Team
+ * @brief DelayBlock Low Layer HAL module driver.
+ *
+ * This file provides firmware functions to manage the following
+ * functionalities of the Delay Block peripheral:
+ * + input clock frequency range 25MHz to 208MHz
+ * + up to 12 oversampling phases
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### DelayBlock peripheral features #####
+ ==============================================================================
+ [..] The Delay block is used to generate an Output clock which is de-phased from the Input
+ clock. The phase of the Output clock is programmed by FW. The Output clock is then used
+ to clock the receive data in i.e. a SDMMC or QSPI interface.
+ The delay is Voltage and Temperature dependent, which may require FW to do re-tuning
+ and recenter the Output clock phase to the receive data.
+
+ [..] The Delay Block features include the following:
+ (+) Input clock frequency range 25MHz to 208MHz.
+ (+) Up to 12 oversampling phases.
+
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ This driver is a considered as a driver of service for external devices drivers
+ that interfaces with the DELAY peripheral.
+ The DelayBlock_Enable() function, enables the DelayBlock instance, configure the delay line length
+ and configure the Output clock phase.
+ The DelayBlock_Disable() function, disables the DelayBlock instance by setting DEN flag to 0.
+
+
+ @endverbatim
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+
+/** @defgroup DELAYBLOCK_LL DELAYBLOCK_LL
+ * @brief Low layer module for Delay Block
+ * @{
+ */
+
+#if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_QSPI_MODULE_ENABLED)
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/** @defgroup DelayBlock_LL_Private_Defines Delay Block Low Layer Private Defines
+ * @{
+ */
+#define DLYB_TIMEOUT 0xFFU
+/**
+ * @}
+ */
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup DelayBlock_LL_Exported_Functions Delay Block Low Layer Exported Functions
+ * @{
+ */
+
+/** @defgroup HAL_DELAY_LL_Group1 Initialization de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization and de-initialization functions #####
+ ===============================================================================
+ [..] This section provides functions allowing to:
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Enable the Delay Block instance.
+ * @param DLYBx: Pointer to DLYB instance.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef DelayBlock_Enable(DLYB_TypeDef *DLYBx)
+{
+ uint32_t unit = 0U;
+ uint32_t sel = 0U;
+ uint32_t sel_current;
+ uint32_t unit_current;
+ uint32_t tuning;
+ uint32_t lng_mask;
+ uint32_t tickstart;
+
+ DLYBx->CR = DLYB_CR_DEN | DLYB_CR_SEN;
+
+ for (sel_current = 0U; sel_current < DLYB_MAX_SELECT; sel_current++)
+ {
+ /* lng_mask is the mask bit for the LNG field to check the output of the UNITx*/
+ lng_mask = DLYB_CFGR_LNG_0 << sel_current;
+ tuning = 0U;
+ for (unit_current = 0U; unit_current < DLYB_MAX_UNIT; unit_current++)
+ {
+ /* Set the Delay of the UNIT(s)*/
+ DLYBx->CFGR = DLYB_MAX_SELECT | (unit_current << DLYB_CFGR_UNIT_Pos);
+
+ /* Waiting for a LNG valid value */
+ tickstart = HAL_GetTick();
+ while ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)
+ {
+ if((HAL_GetTick() - tickstart) >= DLYB_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ if (tuning == 0U)
+ {
+ if ((DLYBx->CFGR & lng_mask) != 0U)
+ {
+ /* 1/2 period HIGH is detected */
+ tuning = 1U;
+ }
+ }
+ else
+ {
+ /* 1/2 period LOW detected after the HIGH 1/2 period => FULL PERIOD passed*/
+ if((DLYBx->CFGR & lng_mask ) == 0U)
+ {
+ /* Save the first result */
+ if( unit == 0U )
+ {
+ unit = unit_current;
+ sel = sel_current + 1U;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ /* Apply the Tuning settings */
+ DLYBx->CR = 0U;
+ DLYBx->CR = DLYB_CR_DEN | DLYB_CR_SEN;
+ DLYBx->CFGR = sel | (unit << DLYB_CFGR_UNIT_Pos);
+ DLYBx->CR = DLYB_CR_DEN;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disable the Delay Block instance.
+ * @param DLYBx: Pointer to DLYB instance.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef DelayBlock_Disable(DLYB_TypeDef *DLYBx)
+{
+ /* Disable DLYB */
+ DLYBx->CR = 0U;
+ return HAL_OK;
+}
+
+/**
+ * @brief Configure the Delay Block instance.
+ * @param DLYBx: Pointer to DLYB instance.
+ * @param PhaseSel: Phase selection [0..11].
+ * @param Units: Delay units[0..127].
+ * @retval HAL status
+ */
+HAL_StatusTypeDef DelayBlock_Configure(DLYB_TypeDef *DLYBx,uint32_t PhaseSel, uint32_t Units )
+{
+ /* Apply the delay settings */
+
+ DLYBx->CR = 0U;
+ DLYBx->CR = DLYB_CR_DEN | DLYB_CR_SEN;
+ DLYBx->CFGR = PhaseSel | (Units << DLYB_CFGR_UNIT_Pos);
+ DLYBx->CR = DLYB_CR_DEN;
+
+ return HAL_OK;
+}
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* (HAL_SD_MODULE_ENABLED) & (HAL_QSPI_MODULE_ENABLED)*/
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c
new file mode 100755
index 0000000..b9ce32d
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c
@@ -0,0 +1,1090 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_fmc.c
+ * @author MCD Application Team
+ * @brief FMC Low Layer HAL module driver.
+ *
+ * This file provides firmware functions to manage the following
+ * functionalities of the Flexible Memory Controller (FMC) peripheral memories:
+ * + Initialization/de-initialization functions
+ * + Peripheral Control functions
+ * + Peripheral State functions
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### FMC peripheral features #####
+ ==============================================================================
+ [..] The Flexible memory controller (FMC) includes following memory controllers:
+ (+) The NOR/PSRAM memory controller
+ (+) The NAND memory controller
+ (+) The Synchronous DRAM (SDRAM) controller
+
+ [..] The FMC functional block makes the interface with synchronous and asynchronous static
+ memories and SDRAM memories. Its main purposes are:
+ (+) to translate AHB transactions into the appropriate external device protocol
+ (+) to meet the access time requirements of the external memory devices
+
+ [..] All external memories share the addresses, data and control signals with the controller.
+ Each external device is accessed by means of a unique Chip Select. The FMC performs
+ only one access at a time to an external device.
+ The main features of the FMC controller are the following:
+ (+) Interface with static-memory mapped devices including:
+ (++) Static random access memory (SRAM)
+ (++) Read-only memory (ROM)
+ (++) NOR Flash memory/OneNAND Flash memory
+ (++) PSRAM (4 memory banks)
+ (++) Two banks of NAND Flash memory with ECC hardware to check up to 8 Kbytes of
+ data
+ (+) Interface with synchronous DRAM (SDRAM) memories
+ (+) Independent Chip Select control for each memory bank
+ (+) Independent configuration for each memory bank
+
+ @endverbatim
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_HAL_Driver
+ * @{
+ */
+#if defined(HAL_NOR_MODULE_ENABLED) || defined(HAL_NAND_MODULE_ENABLED) || defined(HAL_SDRAM_MODULE_ENABLED)\
+ || defined(HAL_SRAM_MODULE_ENABLED)
+
+/** @defgroup FMC_LL FMC Low Layer
+ * @brief FMC driver modules
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/** @defgroup FMC_LL_Private_Constants FMC Low Layer Private Constants
+ * @{
+ */
+
+/* ----------------------- FMC registers bit mask --------------------------- */
+
+/* --- BCR Register ---*/
+/* BCR register clear mask */
+
+/* --- BTR Register ---*/
+/* BTR register clear mask */
+#define BTR_CLEAR_MASK ((uint32_t)(FMC_BTRx_ADDSET | FMC_BTRx_ADDHLD |\
+ FMC_BTRx_DATAST | FMC_BTRx_BUSTURN |\
+ FMC_BTRx_CLKDIV | FMC_BTRx_DATLAT |\
+ FMC_BTRx_ACCMOD))
+
+/* --- BWTR Register ---*/
+/* BWTR register clear mask */
+#define BWTR_CLEAR_MASK ((uint32_t)(FMC_BWTRx_ADDSET | FMC_BWTRx_ADDHLD |\
+ FMC_BWTRx_DATAST | FMC_BWTRx_BUSTURN |\
+ FMC_BWTRx_ACCMOD))
+
+/* --- PCR Register ---*/
+/* PCR register clear mask */
+#define PCR_CLEAR_MASK ((uint32_t)(FMC_PCR_PWAITEN | FMC_PCR_PBKEN | \
+ FMC_PCR_PWID | FMC_PCR_ECCEN | \
+ FMC_PCR_TCLR | FMC_PCR_TAR | \
+ FMC_PCR_ECCPS))
+/* --- PMEM Register ---*/
+/* PMEM register clear mask */
+#define PMEM_CLEAR_MASK ((uint32_t)(FMC_PMEM_MEMSET | FMC_PMEM_MEMWAIT |\
+ FMC_PMEM_MEMHOLD | FMC_PMEM_MEMHIZ))
+
+/* --- PATT Register ---*/
+/* PATT register clear mask */
+#define PATT_CLEAR_MASK ((uint32_t)(FMC_PATT_ATTSET | FMC_PATT_ATTWAIT |\
+ FMC_PATT_ATTHOLD | FMC_PATT_ATTHIZ))
+
+
+/* --- SDCR Register ---*/
+/* SDCR register clear mask */
+#define SDCR_CLEAR_MASK ((uint32_t)(FMC_SDCRx_NC | FMC_SDCRx_NR | \
+ FMC_SDCRx_MWID | FMC_SDCRx_NB | \
+ FMC_SDCRx_CAS | FMC_SDCRx_WP | \
+ FMC_SDCRx_SDCLK | FMC_SDCRx_RBURST | \
+ FMC_SDCRx_RPIPE))
+
+/* --- SDTR Register ---*/
+/* SDTR register clear mask */
+#define SDTR_CLEAR_MASK ((uint32_t)(FMC_SDTRx_TMRD | FMC_SDTRx_TXSR | \
+ FMC_SDTRx_TRAS | FMC_SDTRx_TRC | \
+ FMC_SDTRx_TWR | FMC_SDTRx_TRP | \
+ FMC_SDTRx_TRCD))
+
+/**
+ * @}
+ */
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/
+
+/** @defgroup FMC_LL_Exported_Functions FMC Low Layer Exported Functions
+ * @{
+ */
+
+
+/** @defgroup FMC_LL_Exported_Functions_NORSRAM FMC Low Layer NOR SRAM Exported Functions
+ * @brief NORSRAM Controller functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use NORSRAM device driver #####
+ ==============================================================================
+
+ [..]
+ This driver contains a set of APIs to interface with the FMC NORSRAM banks in order
+ to run the NORSRAM external devices.
+
+ (+) FMC NORSRAM bank reset using the function FMC_NORSRAM_DeInit()
+ (+) FMC NORSRAM bank control configuration using the function FMC_NORSRAM_Init()
+ (+) FMC NORSRAM bank timing configuration using the function FMC_NORSRAM_Timing_Init()
+ (+) FMC NORSRAM bank extended timing configuration using the function
+ FMC_NORSRAM_Extended_Timing_Init()
+ (+) FMC NORSRAM bank enable/disable write operation using the functions
+ FMC_NORSRAM_WriteOperation_Enable()/FMC_NORSRAM_WriteOperation_Disable()
+
+@endverbatim
+ * @{
+ */
+
+/** @defgroup FMC_LL_NORSRAM_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 FMC NORSRAM interface
+ (+) De-initialize the FMC NORSRAM interface
+ (+) Configure the FMC clock and associated GPIOs
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initialize the FMC_NORSRAM device according to the specified
+ * control parameters in the FMC_NORSRAM_InitTypeDef
+ * @param Device Pointer to NORSRAM device instance
+ * @param Init Pointer to NORSRAM Initialization structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NORSRAM_Init(FMC_NORSRAM_TypeDef *Device,
+ const FMC_NORSRAM_InitTypeDef *Init)
+{
+ uint32_t flashaccess;
+ uint32_t btcr_reg;
+ uint32_t mask;
+
+ /* Check the parameters */
+ assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+ assert_param(IS_FMC_NORSRAM_BANK(Init->NSBank));
+ assert_param(IS_FMC_MUX(Init->DataAddressMux));
+ assert_param(IS_FMC_MEMORY(Init->MemoryType));
+ assert_param(IS_FMC_NORSRAM_MEMORY_WIDTH(Init->MemoryDataWidth));
+ assert_param(IS_FMC_BURSTMODE(Init->BurstAccessMode));
+ assert_param(IS_FMC_WAIT_POLARITY(Init->WaitSignalPolarity));
+ assert_param(IS_FMC_WAIT_SIGNAL_ACTIVE(Init->WaitSignalActive));
+ assert_param(IS_FMC_WRITE_OPERATION(Init->WriteOperation));
+ assert_param(IS_FMC_WAITE_SIGNAL(Init->WaitSignal));
+ assert_param(IS_FMC_EXTENDED_MODE(Init->ExtendedMode));
+ assert_param(IS_FMC_ASYNWAIT(Init->AsynchronousWait));
+ assert_param(IS_FMC_WRITE_BURST(Init->WriteBurst));
+ assert_param(IS_FMC_CONTINOUS_CLOCK(Init->ContinuousClock));
+ assert_param(IS_FMC_WRITE_FIFO(Init->WriteFifo));
+ assert_param(IS_FMC_PAGESIZE(Init->PageSize));
+
+ /* Disable NORSRAM Device */
+ __FMC_NORSRAM_DISABLE(Device, Init->NSBank);
+
+ /* Set NORSRAM device control parameters */
+ if (Init->MemoryType == FMC_MEMORY_TYPE_NOR)
+ {
+ flashaccess = FMC_NORSRAM_FLASH_ACCESS_ENABLE;
+ }
+ else
+ {
+ flashaccess = FMC_NORSRAM_FLASH_ACCESS_DISABLE;
+ }
+
+ btcr_reg = (flashaccess | \
+ Init->DataAddressMux | \
+ Init->MemoryType | \
+ Init->MemoryDataWidth | \
+ Init->BurstAccessMode | \
+ Init->WaitSignalPolarity | \
+ Init->WaitSignalActive | \
+ Init->WriteOperation | \
+ Init->WaitSignal | \
+ Init->ExtendedMode | \
+ Init->AsynchronousWait | \
+ Init->WriteBurst);
+
+ btcr_reg |= Init->ContinuousClock;
+ btcr_reg |= Init->WriteFifo;
+ btcr_reg |= Init->PageSize;
+
+ mask = (FMC_BCRx_MBKEN |
+ FMC_BCRx_MUXEN |
+ FMC_BCRx_MTYP |
+ FMC_BCRx_MWID |
+ FMC_BCRx_FACCEN |
+ FMC_BCRx_BURSTEN |
+ FMC_BCRx_WAITPOL |
+ FMC_BCRx_WAITCFG |
+ FMC_BCRx_WREN |
+ FMC_BCRx_WAITEN |
+ FMC_BCRx_EXTMOD |
+ FMC_BCRx_ASYNCWAIT |
+ FMC_BCRx_CBURSTRW);
+
+ mask |= FMC_BCR1_CCLKEN;
+ mask |= FMC_BCR1_WFDIS;
+ mask |= FMC_BCRx_CPSIZE;
+
+ MODIFY_REG(Device->BTCR[Init->NSBank], mask, btcr_reg);
+
+ /* Configure synchronous mode when Continuous clock is enabled for bank2..4 */
+ if ((Init->ContinuousClock == FMC_CONTINUOUS_CLOCK_SYNC_ASYNC) && (Init->NSBank != FMC_NORSRAM_BANK1))
+ {
+ MODIFY_REG(Device->BTCR[FMC_NORSRAM_BANK1], FMC_BCR1_CCLKEN, Init->ContinuousClock);
+ }
+
+ if (Init->NSBank != FMC_NORSRAM_BANK1)
+ {
+ /* Configure Write FIFO mode when Write Fifo is enabled for bank2..4 */
+ SET_BIT(Device->BTCR[FMC_NORSRAM_BANK1], (uint32_t)(Init->WriteFifo));
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitialize the FMC_NORSRAM peripheral
+ * @param Device Pointer to NORSRAM device instance
+ * @param ExDevice Pointer to NORSRAM extended mode device instance
+ * @param Bank NORSRAM bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NORSRAM_DeInit(FMC_NORSRAM_TypeDef *Device,
+ FMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+ assert_param(IS_FMC_NORSRAM_EXTENDED_DEVICE(ExDevice));
+ assert_param(IS_FMC_NORSRAM_BANK(Bank));
+
+ /* Disable the FMC_NORSRAM device */
+ __FMC_NORSRAM_DISABLE(Device, Bank);
+
+ /* De-initialize the FMC_NORSRAM device */
+ /* FMC_NORSRAM_BANK1 */
+ if (Bank == FMC_NORSRAM_BANK1)
+ {
+ Device->BTCR[Bank] = 0x000030DBU;
+ }
+ /* FMC_NORSRAM_BANK2, FMC_NORSRAM_BANK3 or FMC_NORSRAM_BANK4 */
+ else
+ {
+ Device->BTCR[Bank] = 0x000030D2U;
+ }
+
+ Device->BTCR[Bank + 1U] = 0x0FFFFFFFU;
+ ExDevice->BWTR[Bank] = 0x0FFFFFFFU;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the FMC_NORSRAM Timing according to the specified
+ * parameters in the FMC_NORSRAM_TimingTypeDef
+ * @param Device Pointer to NORSRAM device instance
+ * @param Timing Pointer to NORSRAM Timing structure
+ * @param Bank NORSRAM bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NORSRAM_Timing_Init(FMC_NORSRAM_TypeDef *Device,
+ const FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank)
+{
+ uint32_t tmpr;
+
+ /* Check the parameters */
+ assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+ assert_param(IS_FMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
+ assert_param(IS_FMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
+ assert_param(IS_FMC_DATASETUP_TIME(Timing->DataSetupTime));
+ assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
+ assert_param(IS_FMC_CLK_DIV(Timing->CLKDivision));
+ assert_param(IS_FMC_DATA_LATENCY(Timing->DataLatency));
+ assert_param(IS_FMC_ACCESS_MODE(Timing->AccessMode));
+ assert_param(IS_FMC_NORSRAM_BANK(Bank));
+
+ /* Set FMC_NORSRAM device timing parameters */
+ Device->BTCR[Bank + 1U] =
+ (Timing->AddressSetupTime << FMC_BTRx_ADDSET_Pos) |
+ (Timing->AddressHoldTime << FMC_BTRx_ADDHLD_Pos) |
+ (Timing->DataSetupTime << FMC_BTRx_DATAST_Pos) |
+ (Timing->BusTurnAroundDuration << FMC_BTRx_BUSTURN_Pos) |
+ ((Timing->CLKDivision - 1U) << FMC_BTRx_CLKDIV_Pos) |
+ ((Timing->DataLatency - 2U) << FMC_BTRx_DATLAT_Pos) |
+ Timing->AccessMode;
+
+ /* Configure Clock division value (in NORSRAM bank 1) when continuous clock is enabled */
+ if (HAL_IS_BIT_SET(Device->BTCR[FMC_NORSRAM_BANK1], FMC_BCR1_CCLKEN))
+ {
+ tmpr = (uint32_t)(Device->BTCR[FMC_NORSRAM_BANK1 + 1U] & ~((0x0FUL) << FMC_BTRx_CLKDIV_Pos));
+ tmpr |= (uint32_t)(((Timing->CLKDivision) - 1U) << FMC_BTRx_CLKDIV_Pos);
+ MODIFY_REG(Device->BTCR[FMC_NORSRAM_BANK1 + 1U], FMC_BTRx_CLKDIV, tmpr);
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initialize the FMC_NORSRAM Extended mode Timing according to the specified
+ * parameters in the FMC_NORSRAM_TimingTypeDef
+ * @param Device Pointer to NORSRAM device instance
+ * @param Timing Pointer to NORSRAM Timing structure
+ * @param Bank NORSRAM bank number
+ * @param ExtendedMode FMC Extended Mode
+ * This parameter can be one of the following values:
+ * @arg FMC_EXTENDED_MODE_DISABLE
+ * @arg FMC_EXTENDED_MODE_ENABLE
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_EXTENDED_TypeDef *Device,
+ const FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank,
+ uint32_t ExtendedMode)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_EXTENDED_MODE(ExtendedMode));
+
+ /* Set NORSRAM device timing register for write configuration, if extended mode is used */
+ if (ExtendedMode == FMC_EXTENDED_MODE_ENABLE)
+ {
+ /* Check the parameters */
+ assert_param(IS_FMC_NORSRAM_EXTENDED_DEVICE(Device));
+ assert_param(IS_FMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
+ assert_param(IS_FMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
+ assert_param(IS_FMC_DATASETUP_TIME(Timing->DataSetupTime));
+ assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
+ assert_param(IS_FMC_ACCESS_MODE(Timing->AccessMode));
+ assert_param(IS_FMC_NORSRAM_BANK(Bank));
+
+ /* Set NORSRAM device timing register for write configuration, if extended mode is used */
+ MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime |
+ ((Timing->AddressHoldTime) << FMC_BWTRx_ADDHLD_Pos) |
+ ((Timing->DataSetupTime) << FMC_BWTRx_DATAST_Pos) |
+ Timing->AccessMode |
+ ((Timing->BusTurnAroundDuration) << FMC_BWTRx_BUSTURN_Pos)));
+ }
+ else
+ {
+ Device->BWTR[Bank] = 0x0FFFFFFFU;
+ }
+
+ return HAL_OK;
+}
+/**
+ * @}
+ */
+
+/** @addtogroup FMC_LL_NORSRAM_Private_Functions_Group2
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### FMC_NORSRAM Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the FMC NORSRAM interface.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables dynamically FMC_NORSRAM write operation.
+ * @param Device Pointer to NORSRAM device instance
+ * @param Bank NORSRAM bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Enable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+ assert_param(IS_FMC_NORSRAM_BANK(Bank));
+
+ /* Enable write operation */
+ SET_BIT(Device->BTCR[Bank], FMC_WRITE_OPERATION_ENABLE);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically FMC_NORSRAM write operation.
+ * @param Device Pointer to NORSRAM device instance
+ * @param Bank NORSRAM bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Disable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NORSRAM_DEVICE(Device));
+ assert_param(IS_FMC_NORSRAM_BANK(Bank));
+
+ /* Disable write operation */
+ CLEAR_BIT(Device->BTCR[Bank], FMC_WRITE_OPERATION_ENABLE);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup FMC_LL_Exported_Functions_NAND FMC Low Layer NAND Exported Functions
+ * @brief NAND Controller functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use NAND device driver #####
+ ==============================================================================
+ [..]
+ This driver contains a set of APIs to interface with the FMC NAND banks in order
+ to run the NAND external devices.
+
+ (+) FMC NAND bank reset using the function FMC_NAND_DeInit()
+ (+) FMC NAND bank control configuration using the function FMC_NAND_Init()
+ (+) FMC NAND bank common space timing configuration using the function
+ FMC_NAND_CommonSpace_Timing_Init()
+ (+) FMC NAND bank attribute space timing configuration using the function
+ FMC_NAND_AttributeSpace_Timing_Init()
+ (+) FMC NAND bank enable/disable ECC correction feature using the functions
+ FMC_NAND_ECC_Enable()/FMC_NAND_ECC_Disable()
+ (+) FMC NAND bank get ECC correction code using the function FMC_NAND_GetECC()
+
+@endverbatim
+ * @{
+ */
+
+/** @defgroup FMC_LL_NAND_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 FMC NAND interface
+ (+) De-initialize the FMC NAND interface
+ (+) Configure the FMC clock and associated GPIOs
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the FMC_NAND device according to the specified
+ * control parameters in the FMC_NAND_HandleTypeDef
+ * @param Device Pointer to NAND device instance
+ * @param Init Pointer to NAND Initialization structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_Init(FMC_NAND_TypeDef *Device, const FMC_NAND_InitTypeDef *Init)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_NAND_BANK(Init->NandBank));
+ assert_param(IS_FMC_WAIT_FEATURE(Init->Waitfeature));
+ assert_param(IS_FMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth));
+ assert_param(IS_FMC_ECC_STATE(Init->EccComputation));
+ assert_param(IS_FMC_ECCPAGE_SIZE(Init->ECCPageSize));
+ assert_param(IS_FMC_TCLR_TIME(Init->TCLRSetupTime));
+ assert_param(IS_FMC_TAR_TIME(Init->TARSetupTime));
+
+ /* NAND bank 3 registers configuration */
+ MODIFY_REG(Device->PCR, PCR_CLEAR_MASK, (Init->Waitfeature |
+ FMC_PCR_MEMORY_TYPE_NAND |
+ Init->MemoryDataWidth |
+ Init->EccComputation |
+ Init->ECCPageSize |
+ ((Init->TCLRSetupTime) << FMC_PCR_TCLR_Pos) |
+ ((Init->TARSetupTime) << FMC_PCR_TAR_Pos)));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the FMC_NAND Common space Timing according to the specified
+ * parameters in the FMC_NAND_PCC_TimingTypeDef
+ * @param Device Pointer to NAND device instance
+ * @param Timing Pointer to NAND timing structure
+ * @param Bank NAND bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_CommonSpace_Timing_Init(FMC_NAND_TypeDef *Device,
+ const FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+ assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+ assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+ assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+ assert_param(IS_FMC_NAND_BANK(Bank));
+
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(Bank);
+
+ /* NAND bank 3 registers configuration */
+ Device->PMEM = (Timing->SetupTime |
+ ((Timing->WaitSetupTime) << FMC_PMEM_MEMWAIT_Pos) |
+ ((Timing->HoldSetupTime) << FMC_PMEM_MEMHOLD_Pos) |
+ ((Timing->HiZSetupTime) << FMC_PMEM_MEMHIZ_Pos));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Initializes the FMC_NAND Attribute space Timing according to the specified
+ * parameters in the FMC_NAND_PCC_TimingTypeDef
+ * @param Device Pointer to NAND device instance
+ * @param Timing Pointer to NAND timing structure
+ * @param Bank NAND bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_AttributeSpace_Timing_Init(FMC_NAND_TypeDef *Device,
+ const FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime));
+ assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime));
+ assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime));
+ assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime));
+ assert_param(IS_FMC_NAND_BANK(Bank));
+
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(Bank);
+
+ /* NAND bank 3 registers configuration */
+ Device->PATT = (Timing->SetupTime |
+ ((Timing->WaitSetupTime) << FMC_PATT_ATTWAIT_Pos) |
+ ((Timing->HoldSetupTime) << FMC_PATT_ATTHOLD_Pos) |
+ ((Timing->HiZSetupTime) << FMC_PATT_ATTHIZ_Pos));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the FMC_NAND device
+ * @param Device Pointer to NAND device instance
+ * @param Bank NAND bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_DeInit(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_NAND_BANK(Bank));
+
+ /* Disable the NAND Bank */
+ __FMC_NAND_DISABLE(Device, Bank);
+
+ /* De-initialize the NAND Bank */
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(Bank);
+
+ /* Set the FMC_NAND_BANK3 registers to their reset values */
+ WRITE_REG(Device->PCR, 0x00000018U);
+ WRITE_REG(Device->SR, 0x00000040U);
+ WRITE_REG(Device->PMEM, 0xFCFCFCFCU);
+ WRITE_REG(Device->PATT, 0xFCFCFCFCU);
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup HAL_FMC_NAND_Group2 Peripheral Control functions
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### FMC_NAND Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the FMC NAND interface.
+
+@endverbatim
+ * @{
+ */
+
+
+/**
+ * @brief Enables dynamically FMC_NAND ECC feature.
+ * @param Device Pointer to NAND device instance
+ * @param Bank NAND bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_ECC_Enable(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_NAND_BANK(Bank));
+
+ /* Enable ECC feature */
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(Bank);
+
+ SET_BIT(Device->PCR, FMC_PCR_ECCEN);
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Disables dynamically FMC_NAND ECC feature.
+ * @param Device Pointer to NAND device instance
+ * @param Bank NAND bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_ECC_Disable(FMC_NAND_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_NAND_BANK(Bank));
+
+ /* Disable ECC feature */
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(Bank);
+
+ CLEAR_BIT(Device->PCR, FMC_PCR_ECCEN);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically FMC_NAND ECC feature.
+ * @param Device Pointer to NAND device instance
+ * @param ECCval Pointer to ECC value
+ * @param Bank NAND bank number
+ * @param Timeout Timeout wait value
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_NAND_GetECC(const FMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank,
+ uint32_t Timeout)
+{
+ uint32_t tickstart;
+
+ /* Check the parameters */
+ assert_param(IS_FMC_NAND_DEVICE(Device));
+ assert_param(IS_FMC_NAND_BANK(Bank));
+
+ /* Get tick */
+ tickstart = HAL_GetTick();
+
+ /* Wait until FIFO is empty */
+ while (__FMC_NAND_GET_FLAG(Device, Bank, FMC_FLAG_FEMPT) == RESET)
+ {
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Prevent unused argument(s) compilation warning if no assert_param check */
+ UNUSED(Bank);
+
+ /* Get the ECCR register value */
+ *ECCval = (uint32_t)Device->ECCR;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @defgroup FMC_LL_SDRAM
+ * @brief SDRAM Controller functions
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use SDRAM device driver #####
+ ==============================================================================
+ [..]
+ This driver contains a set of APIs to interface with the FMC SDRAM banks in order
+ to run the SDRAM external devices.
+
+ (+) FMC SDRAM bank reset using the function FMC_SDRAM_DeInit()
+ (+) FMC SDRAM bank control configuration using the function FMC_SDRAM_Init()
+ (+) FMC SDRAM bank timing configuration using the function FMC_SDRAM_Timing_Init()
+ (+) FMC SDRAM bank enable/disable write operation using the functions
+ FMC_SDRAM_WriteOperation_Enable()/FMC_SDRAM_WriteOperation_Disable()
+ (+) FMC SDRAM bank send command using the function FMC_SDRAM_SendCommand()
+
+@endverbatim
+ * @{
+ */
+
+/** @addtogroup FMC_LL_SDRAM_Private_Functions_Group1
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ==============================================================================
+ ##### Initialization and de_initialization functions #####
+ ==============================================================================
+ [..]
+ This section provides functions allowing to:
+ (+) Initialize and configure the FMC SDRAM interface
+ (+) De-initialize the FMC SDRAM interface
+ (+) Configure the FMC clock and associated GPIOs
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Initializes the FMC_SDRAM device according to the specified
+ * control parameters in the FMC_SDRAM_InitTypeDef
+ * @param Device Pointer to SDRAM device instance
+ * @param Init Pointer to SDRAM Initialization structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, const FMC_SDRAM_InitTypeDef *Init)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_SDRAM_BANK(Init->SDBank));
+ assert_param(IS_FMC_COLUMNBITS_NUMBER(Init->ColumnBitsNumber));
+ assert_param(IS_FMC_ROWBITS_NUMBER(Init->RowBitsNumber));
+ assert_param(IS_FMC_SDMEMORY_WIDTH(Init->MemoryDataWidth));
+ assert_param(IS_FMC_INTERNALBANK_NUMBER(Init->InternalBankNumber));
+ assert_param(IS_FMC_CAS_LATENCY(Init->CASLatency));
+ assert_param(IS_FMC_WRITE_PROTECTION(Init->WriteProtection));
+ assert_param(IS_FMC_SDCLOCK_PERIOD(Init->SDClockPeriod));
+ assert_param(IS_FMC_READ_BURST(Init->ReadBurst));
+ assert_param(IS_FMC_READPIPE_DELAY(Init->ReadPipeDelay));
+
+ /* Set SDRAM bank configuration parameters */
+ if (Init->SDBank == FMC_SDRAM_BANK1)
+ {
+ MODIFY_REG(Device->SDCR[FMC_SDRAM_BANK1],
+ SDCR_CLEAR_MASK,
+ (Init->ColumnBitsNumber |
+ Init->RowBitsNumber |
+ Init->MemoryDataWidth |
+ Init->InternalBankNumber |
+ Init->CASLatency |
+ Init->WriteProtection |
+ Init->SDClockPeriod |
+ Init->ReadBurst |
+ Init->ReadPipeDelay));
+ }
+ else /* FMC_Bank2_SDRAM */
+ {
+ MODIFY_REG(Device->SDCR[FMC_SDRAM_BANK1],
+ FMC_SDCRx_SDCLK |
+ FMC_SDCRx_RBURST |
+ FMC_SDCRx_RPIPE,
+ (Init->SDClockPeriod |
+ Init->ReadBurst |
+ Init->ReadPipeDelay));
+
+ MODIFY_REG(Device->SDCR[FMC_SDRAM_BANK2],
+ SDCR_CLEAR_MASK,
+ (Init->ColumnBitsNumber |
+ Init->RowBitsNumber |
+ Init->MemoryDataWidth |
+ Init->InternalBankNumber |
+ Init->CASLatency |
+ Init->WriteProtection));
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief Initializes the FMC_SDRAM device timing according to the specified
+ * parameters in the FMC_SDRAM_TimingTypeDef
+ * @param Device Pointer to SDRAM device instance
+ * @param Timing Pointer to SDRAM Timing structure
+ * @param Bank SDRAM bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device,
+ const FMC_SDRAM_TimingTypeDef *Timing, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_LOADTOACTIVE_DELAY(Timing->LoadToActiveDelay));
+ assert_param(IS_FMC_EXITSELFREFRESH_DELAY(Timing->ExitSelfRefreshDelay));
+ assert_param(IS_FMC_SELFREFRESH_TIME(Timing->SelfRefreshTime));
+ assert_param(IS_FMC_ROWCYCLE_DELAY(Timing->RowCycleDelay));
+ assert_param(IS_FMC_WRITE_RECOVERY_TIME(Timing->WriteRecoveryTime));
+ assert_param(IS_FMC_RP_DELAY(Timing->RPDelay));
+ assert_param(IS_FMC_RCD_DELAY(Timing->RCDDelay));
+ assert_param(IS_FMC_SDRAM_BANK(Bank));
+
+ /* Set SDRAM device timing parameters */
+ if (Bank == FMC_SDRAM_BANK1)
+ {
+ MODIFY_REG(Device->SDTR[FMC_SDRAM_BANK1],
+ SDTR_CLEAR_MASK,
+ (((Timing->LoadToActiveDelay) - 1U) |
+ (((Timing->ExitSelfRefreshDelay) - 1U) << FMC_SDTRx_TXSR_Pos) |
+ (((Timing->SelfRefreshTime) - 1U) << FMC_SDTRx_TRAS_Pos) |
+ (((Timing->RowCycleDelay) - 1U) << FMC_SDTRx_TRC_Pos) |
+ (((Timing->WriteRecoveryTime) - 1U) << FMC_SDTRx_TWR_Pos) |
+ (((Timing->RPDelay) - 1U) << FMC_SDTRx_TRP_Pos) |
+ (((Timing->RCDDelay) - 1U) << FMC_SDTRx_TRCD_Pos)));
+ }
+ else /* FMC_Bank2_SDRAM */
+ {
+ MODIFY_REG(Device->SDTR[FMC_SDRAM_BANK1],
+ FMC_SDTRx_TRC |
+ FMC_SDTRx_TRP,
+ (((Timing->RowCycleDelay) - 1U) << FMC_SDTRx_TRC_Pos) |
+ (((Timing->RPDelay) - 1U) << FMC_SDTRx_TRP_Pos));
+
+ MODIFY_REG(Device->SDTR[FMC_SDRAM_BANK2],
+ SDTR_CLEAR_MASK,
+ (((Timing->LoadToActiveDelay) - 1U) |
+ (((Timing->ExitSelfRefreshDelay) - 1U) << FMC_SDTRx_TXSR_Pos) |
+ (((Timing->SelfRefreshTime) - 1U) << FMC_SDTRx_TRAS_Pos) |
+ (((Timing->WriteRecoveryTime) - 1U) << FMC_SDTRx_TWR_Pos) |
+ (((Timing->RCDDelay) - 1U) << FMC_SDTRx_TRCD_Pos)));
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief DeInitializes the FMC_SDRAM peripheral
+ * @param Device Pointer to SDRAM device instance
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_SDRAM_DeInit(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_SDRAM_BANK(Bank));
+
+ /* De-initialize the SDRAM device */
+ Device->SDCR[Bank] = 0x000002D0U;
+ Device->SDTR[Bank] = 0x0FFFFFFFU;
+ Device->SDCMR = 0x00000000U;
+ Device->SDRTR = 0x00000000U;
+ Device->SDSR = 0x00000000U;
+
+ return HAL_OK;
+}
+
+/**
+ * @}
+ */
+
+/** @addtogroup FMC_LL_SDRAMPrivate_Functions_Group2
+ * @brief management functions
+ *
+@verbatim
+ ==============================================================================
+ ##### FMC_SDRAM Control functions #####
+ ==============================================================================
+ [..]
+ This subsection provides a set of functions allowing to control dynamically
+ the FMC SDRAM interface.
+
+@endverbatim
+ * @{
+ */
+
+/**
+ * @brief Enables dynamically FMC_SDRAM write protection.
+ * @param Device Pointer to SDRAM device instance
+ * @param Bank SDRAM bank number
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Enable(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_SDRAM_BANK(Bank));
+
+ /* Enable write protection */
+ SET_BIT(Device->SDCR[Bank], FMC_SDRAM_WRITE_PROTECTION_ENABLE);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Disables dynamically FMC_SDRAM write protection.
+ * @param hsdram FMC_SDRAM handle
+ * @retval HAL status
+ */
+HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Disable(FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_SDRAM_BANK(Bank));
+
+ /* Disable write protection */
+ CLEAR_BIT(Device->SDCR[Bank], FMC_SDRAM_WRITE_PROTECTION_ENABLE);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Send Command to the FMC SDRAM bank
+ * @param Device Pointer to SDRAM device instance
+ * @param Command Pointer to SDRAM command structure
+ * @param Timing Pointer to SDRAM Timing structure
+ * @param Timeout Timeout wait value
+ * @retval HAL state
+ */
+HAL_StatusTypeDef FMC_SDRAM_SendCommand(FMC_SDRAM_TypeDef *Device,
+ const FMC_SDRAM_CommandTypeDef *Command, uint32_t Timeout)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_COMMAND_MODE(Command->CommandMode));
+ assert_param(IS_FMC_COMMAND_TARGET(Command->CommandTarget));
+ assert_param(IS_FMC_AUTOREFRESH_NUMBER(Command->AutoRefreshNumber));
+ assert_param(IS_FMC_MODE_REGISTER(Command->ModeRegisterDefinition));
+
+ /* Set command register */
+ MODIFY_REG(Device->SDCMR, (FMC_SDCMR_MODE | FMC_SDCMR_CTB2 | FMC_SDCMR_CTB1 | FMC_SDCMR_NRFS | FMC_SDCMR_MRD),
+ ((Command->CommandMode) | (Command->CommandTarget) |
+ (((Command->AutoRefreshNumber) - 1U) << FMC_SDCMR_NRFS_Pos) |
+ ((Command->ModeRegisterDefinition) << FMC_SDCMR_MRD_Pos)));
+ /* Prevent unused argument(s) compilation warning */
+ UNUSED(Timeout);
+ return HAL_OK;
+}
+
+/**
+ * @brief Program the SDRAM Memory Refresh rate.
+ * @param Device Pointer to SDRAM device instance
+ * @param RefreshRate The SDRAM refresh rate value.
+ * @retval HAL state
+ */
+HAL_StatusTypeDef FMC_SDRAM_ProgramRefreshRate(FMC_SDRAM_TypeDef *Device, uint32_t RefreshRate)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_REFRESH_RATE(RefreshRate));
+
+ /* Set the refresh rate in command register */
+ MODIFY_REG(Device->SDRTR, FMC_SDRTR_COUNT, (RefreshRate << FMC_SDRTR_COUNT_Pos));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Set the Number of consecutive SDRAM Memory auto Refresh commands.
+ * @param Device Pointer to SDRAM device instance
+ * @param AutoRefreshNumber Specifies the auto Refresh number.
+ * @retval None
+ */
+HAL_StatusTypeDef FMC_SDRAM_SetAutoRefreshNumber(FMC_SDRAM_TypeDef *Device,
+ uint32_t AutoRefreshNumber)
+{
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_AUTOREFRESH_NUMBER(AutoRefreshNumber));
+
+ /* Set the Auto-refresh number in command register */
+ MODIFY_REG(Device->SDCMR, FMC_SDCMR_NRFS, ((AutoRefreshNumber - 1U) << FMC_SDCMR_NRFS_Pos));
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Returns the indicated FMC SDRAM bank mode status.
+ * @param Device Pointer to SDRAM device instance
+ * @param Bank Defines the FMC SDRAM bank. This parameter can be
+ * FMC_Bank1_SDRAM or FMC_Bank2_SDRAM.
+ * @retval The FMC SDRAM bank mode status, could be on of the following values:
+ * FMC_SDRAM_NORMAL_MODE, FMC_SDRAM_SELF_REFRESH_MODE or
+ * FMC_SDRAM_POWER_DOWN_MODE.
+ */
+uint32_t FMC_SDRAM_GetModeStatus(const FMC_SDRAM_TypeDef *Device, uint32_t Bank)
+{
+ uint32_t tmpreg;
+
+ /* Check the parameters */
+ assert_param(IS_FMC_SDRAM_DEVICE(Device));
+ assert_param(IS_FMC_SDRAM_BANK(Bank));
+
+ /* Get the corresponding bank mode */
+ if (Bank == FMC_SDRAM_BANK1)
+ {
+ tmpreg = (uint32_t)(Device->SDSR & FMC_SDSR_MODES1);
+ }
+ else
+ {
+ tmpreg = ((uint32_t)(Device->SDSR & FMC_SDSR_MODES2) >> 2U);
+ }
+
+ /* Return the mode status */
+ return tmpreg;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /* HAL_NOR_MODULE_ENABLED */
+/**
+ * @}
+ */
+/**
+ * @}
+ */
diff --git a/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c
new file mode 100755
index 0000000..890a4d2
--- /dev/null
+++ b/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c
@@ -0,0 +1,2344 @@
+/**
+ ******************************************************************************
+ * @file stm32h7xx_ll_usb.c
+ * @author MCD Application Team
+ * @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
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
+ @verbatim
+ ==============================================================================
+ ##### How to use this driver #####
+ ==============================================================================
+ [..]
+ (#) Fill parameters of Init structure in USB_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
+
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32h7xx_hal.h"
+
+/** @addtogroup STM32H7xx_LL_USB_DRIVER
+ * @{
+ */
+
+#if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
+static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);
+
+/* Exported functions --------------------------------------------------------*/
+/** @defgroup USB_LL_Exported_Functions USB Low Layer Exported Functions
+ * @{
+ */
+
+/** @defgroup USB_LL_Exported_Functions_Group1 Initialization/de-initialization functions
+ * @brief Initialization and Configuration functions
+ *
+@verbatim
+ ===============================================================================
+ ##### Initialization/de-initialization functions #####
+ ===============================================================================
+
+@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)
+{
+ HAL_StatusTypeDef ret;
+ 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 == 1U)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD;
+ }
+
+ /* Reset after a PHY select */
+ ret = USB_CoreReset(USBx);
+ }
+ else /* FS interface (embedded Phy) */
+ {
+ /* Select FS Embedded PHY */
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
+
+ /* Reset after a PHY select */
+ ret = USB_CoreReset(USBx);
+
+ if (cfg.battery_charging_enable == 0U)
+ {
+ /* Activate the USB Transceiver */
+ USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
+ }
+ else
+ {
+ /* Deactivate the USB Transceiver */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
+ }
+ }
+
+ if (cfg.dma_enable == 1U)
+ {
+ /* make sure to reserve 18 fifo Locations for DMA buffers */
+ USBx->GDFIFOCFG &= ~(0xFFFFUL << 16);
+ USBx->GDFIFOCFG |= 0x3EEUL << 16;
+
+ USBx->GAHBCFG &= ~(USB_OTG_GAHBCFG_HBSTLEN);
+ USBx->GAHBCFG |= USB_OTG_GAHBCFG_HBSTLEN_INCR4;
+ USBx->GAHBCFG |= USB_OTG_GAHBCFG_DMAEN;
+ }
+
+ return ret;
+}
+
+
+/**
+ * @brief Set the USB turnaround time
+ * @param USBx USB Instance
+ * @param hclk: AHB clock frequency
+ * @retval USB turnaround time In PHY Clocks number
+ */
+HAL_StatusTypeDef USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef *USBx,
+ uint32_t hclk, uint8_t speed)
+{
+ uint32_t UsbTrd;
+
+ /* The USBTRD is configured according to the tables below, depending on AHB frequency
+ used by application. In the low AHB frequency range it is used to stretch enough the USB response
+ time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access
+ latency to the Data FIFO */
+ if (speed == USBD_FS_SPEED)
+ {
+ if ((hclk >= 14200000U) && (hclk < 15000000U))
+ {
+ /* hclk Clock Range between 14.2-15 MHz */
+ UsbTrd = 0xFU;
+ }
+ else if ((hclk >= 15000000U) && (hclk < 16000000U))
+ {
+ /* hclk Clock Range between 15-16 MHz */
+ UsbTrd = 0xEU;
+ }
+ else if ((hclk >= 16000000U) && (hclk < 17200000U))
+ {
+ /* hclk Clock Range between 16-17.2 MHz */
+ UsbTrd = 0xDU;
+ }
+ else if ((hclk >= 17200000U) && (hclk < 18500000U))
+ {
+ /* hclk Clock Range between 17.2-18.5 MHz */
+ UsbTrd = 0xCU;
+ }
+ else if ((hclk >= 18500000U) && (hclk < 20000000U))
+ {
+ /* hclk Clock Range between 18.5-20 MHz */
+ UsbTrd = 0xBU;
+ }
+ else if ((hclk >= 20000000U) && (hclk < 21800000U))
+ {
+ /* hclk Clock Range between 20-21.8 MHz */
+ UsbTrd = 0xAU;
+ }
+ else if ((hclk >= 21800000U) && (hclk < 24000000U))
+ {
+ /* hclk Clock Range between 21.8-24 MHz */
+ UsbTrd = 0x9U;
+ }
+ else if ((hclk >= 24000000U) && (hclk < 27700000U))
+ {
+ /* hclk Clock Range between 24-27.7 MHz */
+ UsbTrd = 0x8U;
+ }
+ else if ((hclk >= 27700000U) && (hclk < 32000000U))
+ {
+ /* hclk Clock Range between 27.7-32 MHz */
+ UsbTrd = 0x7U;
+ }
+ else /* if(hclk >= 32000000) */
+ {
+ /* hclk Clock Range between 32-200 MHz */
+ UsbTrd = 0x6U;
+ }
+ }
+ else if (speed == USBD_HS_SPEED)
+ {
+ UsbTrd = USBD_HS_TRDT_VALUE;
+ }
+ else
+ {
+ UsbTrd = USBD_DEFAULT_TRDT_VALUE;
+ }
+
+ USBx->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
+ USBx->GUSBCFG |= (uint32_t)((UsbTrd << 10) & USB_OTG_GUSBCFG_TRDT);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_EnableGlobalInt
+ * Enables the controller's Global Int in the AHB Config reg
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
+{
+ USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DisableGlobalInt
+ * Disable the controller's Global Int in the AHB Config reg
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
+{
+ USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_SetCurrentMode Set functional mode
+ * @param USBx Selected device
+ * @param mode current core mode
+ * This parameter can be one of these values:
+ * @arg USB_DEVICE_MODE Peripheral mode
+ * @arg USB_HOST_MODE Host mode
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_OTG_ModeTypeDef mode)
+{
+ uint32_t ms = 0U;
+
+ USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
+
+ if (mode == USB_HOST_MODE)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
+
+ do
+ {
+ HAL_Delay(10U);
+ ms += 10U;
+ } while ((USB_GetMode(USBx) != (uint32_t)USB_HOST_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
+ }
+ else if (mode == USB_DEVICE_MODE)
+ {
+ USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
+
+ do
+ {
+ HAL_Delay(10U);
+ ms += 10U;
+ } while ((USB_GetMode(USBx) != (uint32_t)USB_DEVICE_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ if (ms == HAL_USB_CURRENT_MODE_MAX_DELAY_MS)
+ {
+ return HAL_ERROR;
+ }
+
+ 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)
+{
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t i;
+
+ for (i = 0U; i < 15U; i++)
+ {
+ USBx->DIEPTXF[i] = 0U;
+ }
+
+ /* VBUS Sensing setup */
+ if (cfg.vbus_sensing_enable == 0U)
+ {
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
+
+ /* Deactivate VBUS Sensing B */
+ USBx->GCCFG &= ~USB_OTG_GCCFG_VBDEN;
+
+ /* B-peripheral session valid override enable */
+ USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
+ USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
+ }
+ else
+ {
+ /* Enable HW VBUS sensing */
+ USBx->GCCFG |= USB_OTG_GCCFG_VBDEN;
+ }
+
+ /* Restart the Phy Clock */
+ USBx_PCGCCTL = 0U;
+
+ if (cfg.phy_itface == USB_OTG_ULPI_PHY)
+ {
+ if (cfg.speed == USBD_HS_SPEED)
+ {
+ /* Set Core speed to High speed mode */
+ (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_HIGH);
+ }
+ else
+ {
+ /* Set Core speed to Full speed mode */
+ (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_HIGH_IN_FULL);
+ }
+ }
+ else
+ {
+ /* Set Core speed to Full speed mode */
+ (void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_FULL);
+ }
+
+ /* Flush the FIFOs */
+ if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
+ {
+ ret = HAL_ERROR;
+ }
+
+ if (USB_FlushRxFifo(USBx) != HAL_OK)
+ {
+ ret = HAL_ERROR;
+ }
+
+ /* Clear all pending Device Interrupts */
+ USBx_DEVICE->DIEPMSK = 0U;
+ USBx_DEVICE->DOEPMSK = 0U;
+ USBx_DEVICE->DAINTMSK = 0U;
+
+ for (i = 0U; i < cfg.dev_endpoints; i++)
+ {
+ if ((USBx_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+ {
+ if (i == 0U)
+ {
+ USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
+ }
+ else
+ {
+ USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK;
+ }
+ }
+ else
+ {
+ USBx_INEP(i)->DIEPCTL = 0U;
+ }
+
+ USBx_INEP(i)->DIEPTSIZ = 0U;
+ USBx_INEP(i)->DIEPINT = 0xFB7FU;
+ }
+
+ for (i = 0U; i < cfg.dev_endpoints; i++)
+ {
+ if ((USBx_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+ {
+ if (i == 0U)
+ {
+ USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
+ }
+ else
+ {
+ USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK;
+ }
+ }
+ else
+ {
+ USBx_OUTEP(i)->DOEPCTL = 0U;
+ }
+
+ USBx_OUTEP(i)->DOEPTSIZ = 0U;
+ USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
+ }
+
+ USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM);
+
+ /* Disable all interrupts. */
+ USBx->GINTMSK = 0U;
+
+ /* Clear any pending interrupts */
+ USBx->GINTSTS = 0xBFFFFFFFU;
+
+ /* Enable the common interrupts */
+ if (cfg.dma_enable == 0U)
+ {
+ 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 != 0U)
+ {
+ USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
+ }
+
+ if (cfg.vbus_sensing_enable == 1U)
+ {
+ USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT);
+ }
+
+ return ret;
+}
+
+/**
+ * @brief USB_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)
+{
+ __IO uint32_t count = 0U;
+
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ count++;
+
+ if (count > HAL_USB_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+ /* Flush TX Fifo */
+ count = 0U;
+ USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6));
+
+ do
+ {
+ count++;
+
+ if (count > HAL_USB_TIMEOUT)
+ {
+ 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)
+{
+ __IO uint32_t count = 0U;
+
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ count++;
+
+ if (count > HAL_USB_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+ /* Flush RX Fifo */
+ count = 0U;
+ USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
+
+ do
+ {
+ count++;
+
+ if (count > HAL_USB_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_SetDevSpeed Initializes the DevSpd field of DCFG register
+ * depending the PHY type and the enumeration speed of the device.
+ * @param USBx Selected device
+ * @param speed device speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @retval Hal status
+ */
+HAL_StatusTypeDef USB_SetDevSpeed(const USB_OTG_GlobalTypeDef *USBx, uint8_t speed)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ USBx_DEVICE->DCFG |= speed;
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_GetDevSpeed Return the Dev Speed
+ * @param USBx Selected device
+ * @retval speed device speed
+ * This parameter can be one of these values:
+ * @arg USBD_HS_SPEED: High speed mode
+ * @arg USBD_FS_SPEED: Full speed mode
+ */
+uint8_t USB_GetDevSpeed(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint8_t speed;
+ uint32_t DevEnumSpeed = USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD;
+
+ if (DevEnumSpeed == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ)
+ {
+ speed = USBD_HS_SPEED;
+ }
+ else if ((DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ) ||
+ (DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_48MHZ))
+ {
+ speed = USBD_FS_SPEED;
+ }
+ else
+ {
+ speed = 0xFU;
+ }
+
+ return speed;
+}
+
+#if defined (HAL_PCD_MODULE_ENABLED)
+/**
+ * @brief Activate and configure an endpoint
+ * @param USBx Selected device
+ * @param ep pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ if (ep->is_in == 1U)
+ {
+ USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
+
+ if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0U)
+ {
+ USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
+ ((uint32_t)ep->type << 18) | (epnum << 22) |
+ USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+ USB_OTG_DIEPCTL_USBAEP;
+ }
+ }
+ else
+ {
+ USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
+
+ if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
+ ((uint32_t)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(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1U)
+ {
+ if (((USBx_INEP(epnum)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0U)
+ {
+ USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
+ ((uint32_t)ep->type << 18) | (epnum << 22) |
+ USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+ USB_OTG_DIEPCTL_USBAEP;
+ }
+
+ USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
+ }
+ else
+ {
+ if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
+ ((uint32_t)ep->type << 18) | (epnum << 22) |
+ USB_OTG_DOEPCTL_USBAEP;
+ }
+
+ USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 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(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1U)
+ {
+ if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
+ }
+
+ USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+ USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_USBAEP |
+ USB_OTG_DIEPCTL_MPSIZ |
+ USB_OTG_DIEPCTL_TXFNUM |
+ USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
+ USB_OTG_DIEPCTL_EPTYP);
+ }
+ else
+ {
+ if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
+ }
+
+ USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
+ USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_USBAEP |
+ USB_OTG_DOEPCTL_MPSIZ |
+ USB_OTG_DOEPCTL_SD0PID_SEVNFRM |
+ USB_OTG_DOEPCTL_EPTYP);
+ }
+
+ 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(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ /* Read DEPCTLn register */
+ if (ep->is_in == 1U)
+ {
+ if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
+ }
+
+ USBx_INEP(epnum)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
+ }
+ else
+ {
+ if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
+ }
+
+ USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
+ USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_EPStartXfer : setup and starts a transfer over an EP
+ * @param USBx Selected device
+ * @param ep pointer to endpoint structure
+ * @param dma USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep, uint8_t dma)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+ uint16_t pktcnt;
+
+ /* IN endpoint */
+ if (ep->is_in == 1U)
+ {
+ /* Zero Length Packet? */
+ if (ep->xfer_len == 0U)
+ {
+ USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1UL << 19));
+ USBx_INEP(epnum)->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(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
+ USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
+
+ if (epnum == 0U)
+ {
+ if (ep->xfer_len > ep->maxpacket)
+ {
+ ep->xfer_len = ep->maxpacket;
+ }
+
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1UL << 19));
+ }
+ else
+ {
+ pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19));
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & ((uint32_t)pktcnt << 29));
+ }
+ }
+
+ USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
+ }
+
+ if (dma == 1U)
+ {
+ if ((uint32_t)ep->dma_addr != 0U)
+ {
+ USBx_INEP(epnum)->DIEPDMA = (uint32_t)(ep->dma_addr);
+ }
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ if ((USBx_DEVICE->DSTS & (1UL << 8)) == 0U)
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
+ }
+ else
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
+ }
+ }
+
+ /* EP enable, IN data in FIFO */
+ USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+ }
+ else
+ {
+ /* EP enable, IN data in FIFO */
+ USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
+
+ if (ep->type != EP_TYPE_ISOC)
+ {
+ /* Enable the Tx FIFO Empty Interrupt for this EP */
+ if (ep->xfer_len > 0U)
+ {
+ USBx_DEVICE->DIEPEMPMSK |= 1UL << (ep->num & EP_ADDR_MSK);
+ }
+ }
+ else
+ {
+ if ((USBx_DEVICE->DSTS & (1UL << 8)) == 0U)
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
+ }
+ else
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
+ }
+
+ (void)USB_WritePacket(USBx, ep->xfer_buff, ep->num, (uint16_t)ep->xfer_len, dma);
+ }
+ }
+ }
+ else /* OUT endpoint */
+ {
+ /* Program the transfer size and packet count as follows:
+ * pktcnt = N
+ * xfersize = N * maxpacket
+ */
+ USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
+ USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
+
+ if (epnum == 0U)
+ {
+ if (ep->xfer_len > 0U)
+ {
+ ep->xfer_len = ep->maxpacket;
+ }
+
+ /* Store transfer size, for EP0 this is equal to endpoint max packet size */
+ ep->xfer_size = ep->maxpacket;
+
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size);
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19));
+ }
+ else
+ {
+ if (ep->xfer_len == 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
+ USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19));
+ }
+ else
+ {
+ pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
+ ep->xfer_size = ep->maxpacket * pktcnt;
+
+ USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19);
+ USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size;
+ }
+ }
+
+ if (dma == 1U)
+ {
+ if ((uint32_t)ep->xfer_buff != 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPDMA = (uint32_t)(ep->xfer_buff);
+ }
+ }
+
+ if (ep->type == EP_TYPE_ISOC)
+ {
+ if ((USBx_DEVICE->DSTS & (1UL << 8)) == 0U)
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
+ }
+ else
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
+ }
+ }
+ /* EP enable */
+ USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
+ }
+
+ return HAL_OK;
+}
+
+
+/**
+ * @brief USB_EPStoptXfer Stop transfer on an EP
+ * @param USBx usb device instance
+ * @param ep pointer to endpoint structure
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EPStopXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
+{
+ __IO uint32_t count = 0U;
+ __IO uint32_t RegVal;
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t dma_enable = (USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) >> 0x5U;
+
+ /* IN endpoint */
+ if (ep->is_in == 1U)
+ {
+ /* EP enable, IN data in FIFO */
+ if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
+ {
+ USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_SNAK);
+ USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_EPDIS);
+
+ do
+ {
+ count++;
+
+ if (count > 0xF0000U)
+ {
+ ret = HAL_ERROR;
+ break;
+ }
+ } while (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA);
+ }
+ }
+ else /* OUT endpoint */
+ {
+ USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;
+
+ if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
+ {
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
+ }
+
+ if (dma_enable == 0U)
+ {
+ do
+ {
+ count++;
+
+ if (count > 0xF0000U)
+ {
+ ret = HAL_ERROR;
+ break;
+ }
+ } while (((USBx->GINTSTS & USB_OTG_GINTSTS_RXFLVL) & USB_OTG_GINTSTS_RXFLVL) != USB_OTG_GINTSTS_RXFLVL);
+
+ /* POP the RX status register to generate the NAK Effective interrupt */
+ RegVal = USBx->GRXSTSP;
+ UNUSED(RegVal);
+ }
+
+ /* Wait for Global NAK effective to be set */
+ count = 0U;
+
+ do
+ {
+ count++;
+
+ if (count > 0xF0000U)
+ {
+ ret = HAL_ERROR;
+ break;
+ }
+ } while (((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF)
+ & USB_OTG_GINTSTS_BOUTNAKEFF) != USB_OTG_GINTSTS_BOUTNAKEFF);
+
+ USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_SNAK);
+ USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_EPDIS);
+
+ /* Wait for EP disable to take effect */
+ count = 0U;
+
+ do
+ {
+ count++;
+
+ if (count > 0xF0000U)
+ {
+ ret = HAL_ERROR;
+ break;
+ }
+ } while (((USBx_OUTEP(ep->num)->DOEPINT & USB_OTG_DOEPINT_EPDISD)
+ & USB_OTG_DOEPINT_EPDISD) != USB_OTG_DOEPINT_EPDISD);
+
+ /* Clear OUT EP disable interrupt */
+ USBx_OUTEP(ep->num)->DOEPINT |= USB_OTG_DOEPINT_EPDISD;
+
+ /* Clear Global OUT NAK */
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
+ }
+
+ return ret;
+}
+
+/**
+ * @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(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ if (ep->is_in == 1U)
+ {
+ if (((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == 0U) && (epnum != 0U))
+ {
+ USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS);
+ }
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
+ }
+ else
+ {
+ if (((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == 0U) && (epnum != 0U))
+ {
+ USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS);
+ }
+ USBx_OUTEP(epnum)->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(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t epnum = (uint32_t)ep->num;
+
+ if (ep->is_in == 1U)
+ {
+ USBx_INEP(epnum)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
+ if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
+ {
+ USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
+ }
+ }
+ else
+ {
+ USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
+ if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
+ {
+ USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
+ }
+ }
+ return HAL_OK;
+}
+#endif /* defined (HAL_PCD_MODULE_ENABLED) */
+
+/**
+ * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated
+ * with the EP/channel
+ * @param USBx Selected device
+ * @param src pointer to source buffer
+ * @param ch_ep_num endpoint or host channel number
+ * @param len Number of bytes to write
+ * @param dma USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_WritePacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *src,
+ uint8_t ch_ep_num, uint16_t len, uint8_t dma)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint8_t *pSrc = src;
+ uint32_t count32b;
+ uint32_t i;
+
+ if (dma == 0U)
+ {
+ count32b = ((uint32_t)len + 3U) / 4U;
+ for (i = 0U; i < count32b; i++)
+ {
+ USBx_DFIFO((uint32_t)ch_ep_num) = __UNALIGNED_UINT32_READ(pSrc);
+ pSrc++;
+ pSrc++;
+ pSrc++;
+ pSrc++;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_ReadPacket : read a packet from the RX FIFO
+ * @param USBx Selected device
+ * @param dest source pointer
+ * @param len Number of bytes to read
+ * @retval pointer to destination buffer
+ */
+void *USB_ReadPacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint8_t *pDest = dest;
+ uint32_t pData;
+ uint32_t i;
+ uint32_t count32b = (uint32_t)len >> 2U;
+ uint16_t remaining_bytes = len % 4U;
+
+ for (i = 0U; i < count32b; i++)
+ {
+ __UNALIGNED_UINT32_WRITE(pDest, USBx_DFIFO(0U));
+ pDest++;
+ pDest++;
+ pDest++;
+ pDest++;
+ }
+
+ /* When Number of data is not word aligned, read the remaining byte */
+ if (remaining_bytes != 0U)
+ {
+ i = 0U;
+ __UNALIGNED_UINT32_WRITE(&pData, USBx_DFIFO(0U));
+
+ do
+ {
+ *(uint8_t *)pDest = (uint8_t)(pData >> (8U * (uint8_t)(i)));
+ i++;
+ pDest++;
+ remaining_bytes--;
+ } while (remaining_bytes != 0U);
+ }
+
+ return ((void *)pDest);
+}
+
+/**
+ * @brief USB_StopDevice : Stop the usb device mode
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx)
+{
+ HAL_StatusTypeDef ret;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t i;
+
+ /* Clear Pending interrupt */
+ for (i = 0U; i < 15U; i++)
+ {
+ USBx_INEP(i)->DIEPINT = 0xFB7FU;
+ USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
+ }
+
+ /* Clear interrupt masks */
+ USBx_DEVICE->DIEPMSK = 0U;
+ USBx_DEVICE->DOEPMSK = 0U;
+ USBx_DEVICE->DAINTMSK = 0U;
+
+ /* Flush the FIFO */
+ ret = USB_FlushRxFifo(USBx);
+ if (ret != HAL_OK)
+ {
+ return ret;
+ }
+
+ ret = USB_FlushTxFifo(USBx, 0x10U);
+ if (ret != HAL_OK)
+ {
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @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(const USB_OTG_GlobalTypeDef *USBx, uint8_t address)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ USBx_DEVICE->DCFG &= ~(USB_OTG_DCFG_DAD);
+ USBx_DEVICE->DCFG |= ((uint32_t)address << 4) & USB_OTG_DCFG_DAD;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DevConnect : Connect the USB device by enabling Rpu
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevConnect(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ /* In case phy is stopped, ensure to ungate and restore the phy CLK */
+ USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
+
+ USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DevDisconnect : Disconnect the USB device by disabling Rpu
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DevDisconnect(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ /* In case phy is stopped, ensure to ungate and restore the phy CLK */
+ USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
+
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_ReadInterrupts: return the global USB interrupt status
+ * @param USBx Selected device
+ * @retval USB Global Interrupt status
+ */
+uint32_t USB_ReadInterrupts(USB_OTG_GlobalTypeDef const *USBx)
+{
+ uint32_t tmpreg;
+
+ tmpreg = USBx->GINTSTS;
+ tmpreg &= USBx->GINTMSK;
+
+ return tmpreg;
+}
+
+/**
+ * @brief USB_ReadChInterrupts: return USB channel interrupt status
+ * @param USBx Selected device
+ * @param chnum Channel number
+ * @retval USB Channel Interrupt status
+ */
+uint32_t USB_ReadChInterrupts(const USB_OTG_GlobalTypeDef *USBx, uint8_t chnum)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t tmpreg;
+
+ tmpreg = USBx_HC(chnum)->HCINT;
+ tmpreg &= USBx_HC(chnum)->HCINTMSK;
+
+ return tmpreg;
+}
+
+/**
+ * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
+ * @param USBx Selected device
+ * @retval USB Device OUT EP interrupt status
+ */
+uint32_t USB_ReadDevAllOutEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t tmpreg;
+
+ tmpreg = USBx_DEVICE->DAINT;
+ tmpreg &= USBx_DEVICE->DAINTMSK;
+
+ return ((tmpreg & 0xffff0000U) >> 16);
+}
+
+/**
+ * @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status
+ * @param USBx Selected device
+ * @retval USB Device IN EP interrupt status
+ */
+uint32_t USB_ReadDevAllInEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t tmpreg;
+
+ tmpreg = USBx_DEVICE->DAINT;
+ tmpreg &= USBx_DEVICE->DAINTMSK;
+
+ return ((tmpreg & 0xFFFFU));
+}
+
+/**
+ * @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(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t tmpreg;
+
+ tmpreg = USBx_OUTEP((uint32_t)epnum)->DOEPINT;
+ tmpreg &= USBx_DEVICE->DOEPMSK;
+
+ return tmpreg;
+}
+
+/**
+ * @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(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t tmpreg;
+ uint32_t msk;
+ uint32_t emp;
+
+ msk = USBx_DEVICE->DIEPMSK;
+ emp = USBx_DEVICE->DIEPEMPMSK;
+ msk |= ((emp >> (epnum & EP_ADDR_MSK)) & 0x1U) << 7;
+ tmpreg = USBx_INEP((uint32_t)epnum)->DIEPINT & msk;
+
+ return tmpreg;
+}
+
+/**
+ * @brief USB_ClearInterrupts: clear a USB interrupt
+ * @param USBx Selected device
+ * @param interrupt flag
+ * @retval None
+ */
+void USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
+{
+ USBx->GINTSTS &= interrupt;
+}
+
+/**
+ * @brief Returns USB core mode
+ * @param USBx Selected device
+ * @retval return core mode : Host or Device
+ * This parameter can be one of these values:
+ * 1 : Host
+ * 0 : Device
+ */
+uint32_t USB_GetMode(const USB_OTG_GlobalTypeDef *USBx)
+{
+ return ((USBx->GINTSTS) & 0x1U);
+}
+
+/**
+ * @brief Activate EP0 for Setup transactions
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateSetup(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ /* Set the MPS of the IN EP0 to 64 bytes */
+ USBx_INEP(0U)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ;
+
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Prepare the EP0 to start the first control setup
+ * @param USBx Selected device
+ * @param dma USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @param psetup pointer to setup packet
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_EP0_OutStart(const USB_OTG_GlobalTypeDef *USBx, uint8_t dma, const uint8_t *psetup)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
+
+ if (gSNPSiD > USB_OTG_CORE_ID_300A)
+ {
+ if ((USBx_OUTEP(0U)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
+ {
+ return HAL_OK;
+ }
+ }
+
+ USBx_OUTEP(0U)->DOEPTSIZ = 0U;
+ USBx_OUTEP(0U)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19));
+ USBx_OUTEP(0U)->DOEPTSIZ |= (3U * 8U);
+ USBx_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
+
+ if (dma == 1U)
+ {
+ USBx_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
+ /* EP enable */
+ USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
+ }
+
+ 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)
+{
+ __IO uint32_t count = 0U;
+
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ count++;
+
+ if (count > HAL_USB_TIMEOUT)
+ {
+ return HAL_TIMEOUT;
+ }
+ } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
+
+ count = 10U;
+
+ /* few cycles before setting core reset */
+ while (count > 0U)
+ {
+ count--;
+ }
+
+ /* Core Soft Reset */
+ USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
+
+ do
+ {
+ count++;
+
+ if (count > HAL_USB_TIMEOUT)
+ {
+ 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)
+{
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t i;
+
+ /* Restart the Phy Clock */
+ USBx_PCGCCTL = 0U;
+
+ /* Disable VBUS sensing */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_VBDEN);
+
+ /* Disable Battery chargin detector */
+ USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
+
+
+ if ((USBx->GUSBCFG & USB_OTG_GUSBCFG_PHYSEL) == 0U)
+ {
+ if (cfg.speed == USBH_FSLS_SPEED)
+ {
+ /* Force Device Enumeration to FS/LS mode only */
+ USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS;
+ }
+ else
+ {
+ /* Set default Max speed support */
+ USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
+ }
+ }
+ else
+ {
+ /* Set default Max speed support */
+ USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
+ }
+
+ /* Make sure the FIFOs are flushed. */
+ if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
+ {
+ ret = HAL_ERROR;
+ }
+
+ if (USB_FlushRxFifo(USBx) != HAL_OK)
+ {
+ ret = HAL_ERROR;
+ }
+
+ /* Clear all pending HC Interrupts */
+ for (i = 0U; i < cfg.Host_channels; i++)
+ {
+ USBx_HC(i)->HCINT = CLEAR_INTERRUPT_MASK;
+ USBx_HC(i)->HCINTMSK = 0U;
+ }
+
+ /* Disable all interrupts. */
+ USBx->GINTMSK = 0U;
+
+ /* Clear any pending interrupts */
+ USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
+ /* set Rx FIFO size */
+ USBx->GRXFSIZ = 0x200U;
+ USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x100UL << 16) & USB_OTG_NPTXFD) | 0x200U);
+ USBx->HPTXFSIZ = (uint32_t)(((0xE0UL << 16) & USB_OTG_HPTXFSIZ_PTXFD) | 0x300U);
+
+ /* Enable the common interrupts */
+ if (cfg.dma_enable == 0U)
+ {
+ 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 ret;
+}
+
+/**
+ * @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
+ * HCFG register on the PHY type and set the right frame interval
+ * @param USBx Selected device
+ * @param freq clock frequency
+ * This parameter can be one of these values:
+ * HCFG_48_MHZ : Full Speed 48 MHz Clock
+ * HCFG_6_MHZ : Low Speed 6 MHz Clock
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_InitFSLSPClkSel(const USB_OTG_GlobalTypeDef *USBx, uint8_t freq)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS);
+ USBx_HOST->HCFG |= (uint32_t)freq & USB_OTG_HCFG_FSLSPCS;
+
+ if (freq == HCFG_48_MHZ)
+ {
+ USBx_HOST->HFIR = HFIR_48_MHZ;
+ }
+ else if (freq == HCFG_6_MHZ)
+ {
+ USBx_HOST->HFIR = HFIR_6_MHZ;
+ }
+ else
+ {
+ return HAL_ERROR;
+ }
+
+ 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(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ __IO uint32_t hprt0 = 0U;
+
+ 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(100U); /* See Note #1 */
+ USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0);
+ HAL_Delay(10U);
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DriveVbus : activate or de-activate vbus
+ * @param state VBUS state
+ * This parameter can be one of these values:
+ * 0 : Deactivate VBUS
+ * 1 : Activate VBUS
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DriveVbus(const USB_OTG_GlobalTypeDef *USBx, uint8_t state)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ __IO uint32_t hprt0 = 0U;
+
+ 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) == 0U) && (state == 1U))
+ {
+ USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0);
+ }
+ if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0U))
+ {
+ USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0);
+ }
+ return HAL_OK;
+}
+
+/**
+ * @brief Return Host Port speed
+ * @param USBx Selected device
+ * @retval speed : Host port device speed
+ * This parameter can be one of these values:
+ * @arg HCD_DEVICE_SPEED_HIGH: High speed mode
+ * @arg HCD_DEVICE_SPEED_FULL: Full speed mode
+ * @arg HCD_DEVICE_SPEED_LOW: Low speed mode
+ */
+uint32_t USB_GetHostSpeed(USB_OTG_GlobalTypeDef const *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ __IO uint32_t hprt0 = 0U;
+
+ 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 const *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
+}
+
+#if defined (HAL_HCD_MODULE_ENABLED)
+/**
+ * @brief Initialize a host channel
+ * @param USBx Selected device
+ * @param ch_num Channel number
+ * This parameter can be a value from 1 to 15
+ * @param epnum Endpoint number
+ * This parameter can be a value from 1 to 15
+ * @param dev_address Current device address
+ * This parameter can be a value from 0 to 255
+ * @param speed Current device speed
+ * This parameter can be one of these values:
+ * @arg USB_OTG_SPEED_HIGH: High speed mode
+ * @arg USB_OTG_SPEED_FULL: Full speed mode
+ * @arg USB_OTG_SPEED_LOW: Low speed mode
+ * @param ep_type Endpoint Type
+ * This parameter can be one of these values:
+ * @arg EP_TYPE_CTRL: Control type
+ * @arg EP_TYPE_ISOC: Isochronous type
+ * @arg EP_TYPE_BULK: Bulk type
+ * @arg EP_TYPE_INTR: Interrupt type
+ * @param mps Max Packet Size
+ * This parameter can be a value from 0 to 32K
+ * @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)
+{
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t HCcharEpDir;
+ uint32_t HCcharLowSpeed;
+ uint32_t HostCoreSpeed;
+
+ /* Clear old interrupt conditions for this host channel. */
+ USBx_HC((uint32_t)ch_num)->HCINT = CLEAR_INTERRUPT_MASK;
+
+ /* Enable channel interrupts required for this transfer. */
+ switch (ep_type)
+ {
+ case EP_TYPE_CTRL:
+ case EP_TYPE_BULK:
+ USBx_HC((uint32_t)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 & 0x80U) == 0x80U)
+ {
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
+ }
+ else
+ {
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_NYET |
+ USB_OTG_HCINTMSK_ACKM;
+ }
+ break;
+
+ case EP_TYPE_INTR:
+ USBx_HC((uint32_t)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 & 0x80U) == 0x80U)
+ {
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
+ }
+
+ break;
+
+ case EP_TYPE_ISOC:
+ USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |
+ USB_OTG_HCINTMSK_ACKM |
+ USB_OTG_HCINTMSK_AHBERR |
+ USB_OTG_HCINTMSK_FRMORM;
+
+ if ((epnum & 0x80U) == 0x80U)
+ {
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM);
+ }
+ break;
+
+ default:
+ ret = HAL_ERROR;
+ break;
+ }
+
+ /* Clear Hub Start Split transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT = 0U;
+
+ /* Enable host channel Halt interrupt */
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM;
+
+ /* Enable the top level host channel interrupt. */
+ USBx_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU);
+
+ /* Make sure host channel interrupts are enabled. */
+ USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM;
+
+ /* Program the HCCHAR register */
+ if ((epnum & 0x80U) == 0x80U)
+ {
+ HCcharEpDir = (0x1UL << 15) & USB_OTG_HCCHAR_EPDIR;
+ }
+ else
+ {
+ HCcharEpDir = 0U;
+ }
+
+ HostCoreSpeed = USB_GetHostSpeed(USBx);
+
+ /* LS device plugged to HUB */
+ if ((speed == HPRT0_PRTSPD_LOW_SPEED) && (HostCoreSpeed != HPRT0_PRTSPD_LOW_SPEED))
+ {
+ HCcharLowSpeed = (0x1UL << 17) & USB_OTG_HCCHAR_LSDEV;
+ }
+ else
+ {
+ HCcharLowSpeed = 0U;
+ }
+
+ USBx_HC((uint32_t)ch_num)->HCCHAR = (((uint32_t)dev_address << 22) & USB_OTG_HCCHAR_DAD) |
+ ((((uint32_t)epnum & 0x7FU) << 11) & USB_OTG_HCCHAR_EPNUM) |
+ (((uint32_t)ep_type << 18) & USB_OTG_HCCHAR_EPTYP) |
+ ((uint32_t)mps & USB_OTG_HCCHAR_MPSIZ) |
+ USB_OTG_HCCHAR_MC_0 | HCcharEpDir | HCcharLowSpeed;
+
+ if ((ep_type == EP_TYPE_INTR) || (ep_type == EP_TYPE_ISOC))
+ {
+ USBx_HC((uint32_t)ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Start a transfer over a host channel
+ * @param USBx Selected device
+ * @param hc pointer to host channel structure
+ * @param dma USB dma enabled or disabled
+ * This parameter can be one of these values:
+ * 0 : DMA feature not used
+ * 1 : DMA feature used
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t ch_num = (uint32_t)hc->ch_num;
+ __IO uint32_t tmpreg;
+ uint8_t is_oddframe;
+ uint16_t len_words;
+ uint16_t num_packets;
+ uint16_t max_hc_pkt_count = HC_MAX_PKT_CNT;
+
+ /* in DMA mode host Core automatically issues ping in case of NYET/NAK */
+ if (dma == 1U)
+ {
+ if (((hc->ep_type == EP_TYPE_CTRL) || (hc->ep_type == EP_TYPE_BULK)) && (hc->do_ssplit == 0U))
+ {
+
+ USBx_HC((uint32_t)ch_num)->HCINTMSK &= ~(USB_OTG_HCINTMSK_NYET |
+ USB_OTG_HCINTMSK_ACKM |
+ USB_OTG_HCINTMSK_NAKM);
+ }
+ }
+ else
+ {
+ if ((hc->speed == USBH_HS_SPEED) && (hc->do_ping == 1U))
+ {
+ (void)USB_DoPing(USBx, hc->ch_num);
+ return HAL_OK;
+ }
+ }
+
+ if (hc->do_ssplit == 1U)
+ {
+ /* Set number of packet to 1 for Split transaction */
+ num_packets = 1U;
+
+ if (hc->ep_is_in != 0U)
+ {
+ hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+ }
+ else
+ {
+ if (hc->ep_type == EP_TYPE_ISOC)
+ {
+ if (hc->xfer_len > ISO_SPLT_MPS)
+ {
+ /* Isochrone Max Packet Size for Split mode */
+ hc->XferSize = hc->max_packet;
+ hc->xfer_len = hc->XferSize;
+
+ if ((hc->iso_splt_xactPos == HCSPLT_BEGIN) || (hc->iso_splt_xactPos == HCSPLT_MIDDLE))
+ {
+ hc->iso_splt_xactPos = HCSPLT_MIDDLE;
+ }
+ else
+ {
+ hc->iso_splt_xactPos = HCSPLT_BEGIN;
+ }
+ }
+ else
+ {
+ hc->XferSize = hc->xfer_len;
+
+ if ((hc->iso_splt_xactPos != HCSPLT_BEGIN) && (hc->iso_splt_xactPos != HCSPLT_MIDDLE))
+ {
+ hc->iso_splt_xactPos = HCSPLT_FULL;
+ }
+ else
+ {
+ hc->iso_splt_xactPos = HCSPLT_END;
+ }
+ }
+ }
+ else
+ {
+ if ((dma == 1U) && (hc->xfer_len > hc->max_packet))
+ {
+ hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+ }
+ else
+ {
+ hc->XferSize = hc->xfer_len;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Compute the expected number of packets associated to the transfer */
+ if (hc->xfer_len > 0U)
+ {
+ num_packets = (uint16_t)((hc->xfer_len + hc->max_packet - 1U) / hc->max_packet);
+
+ if (num_packets > max_hc_pkt_count)
+ {
+ num_packets = max_hc_pkt_count;
+ hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+ }
+ }
+ else
+ {
+ num_packets = 1U;
+ }
+
+ /*
+ * For IN channel HCTSIZ.XferSize is expected to be an integer multiple of
+ * max_packet size.
+ */
+ if (hc->ep_is_in != 0U)
+ {
+ hc->XferSize = (uint32_t)num_packets * hc->max_packet;
+ }
+ else
+ {
+ hc->XferSize = hc->xfer_len;
+ }
+ }
+
+ /* Initialize the HCTSIZn register */
+ USBx_HC(ch_num)->HCTSIZ = (hc->XferSize & USB_OTG_HCTSIZ_XFRSIZ) |
+ (((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
+ (((uint32_t)hc->data_pid << 29) & USB_OTG_HCTSIZ_DPID);
+
+ if (dma != 0U)
+ {
+ /* xfer_buff MUST be 32-bits aligned */
+ USBx_HC(ch_num)->HCDMA = (uint32_t)hc->xfer_buff;
+ }
+
+ is_oddframe = (((uint32_t)USBx_HOST->HFNUM & 0x01U) != 0U) ? 0U : 1U;
+ USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
+ USBx_HC(ch_num)->HCCHAR |= (uint32_t)is_oddframe << 29;
+
+ if (hc->do_ssplit == 1U)
+ {
+ /* Set Hub start Split transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT = ((uint32_t)hc->hub_addr << USB_OTG_HCSPLT_HUBADDR_Pos) |
+ (uint32_t)hc->hub_port_nbr | USB_OTG_HCSPLT_SPLITEN;
+
+ /* unmask ack & nyet for IN/OUT transactions */
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_ACKM |
+ USB_OTG_HCINTMSK_NYET);
+
+ if ((hc->do_csplit == 1U) && (hc->ep_is_in == 0U))
+ {
+ USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
+ USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_NYET;
+ }
+
+ if (((hc->ep_type == EP_TYPE_ISOC) || (hc->ep_type == EP_TYPE_INTR)) &&
+ (hc->do_csplit == 1U) && (hc->ep_is_in == 1U))
+ {
+ USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
+ }
+
+ /* Position management for iso out transaction on split mode */
+ if ((hc->ep_type == EP_TYPE_ISOC) && (hc->ep_is_in == 0U))
+ {
+ /* Set data payload position */
+ switch (hc->iso_splt_xactPos)
+ {
+ case HCSPLT_BEGIN:
+ /* First data payload for OUT Transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_1;
+ break;
+
+ case HCSPLT_MIDDLE:
+ /* Middle data payload for OUT Transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_Pos;
+ break;
+
+ case HCSPLT_END:
+ /* End data payload for OUT Transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS_0;
+ break;
+
+ case HCSPLT_FULL:
+ /* Entire data payload for OUT Transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT |= USB_OTG_HCSPLT_XACTPOS;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Clear Hub Start Split transaction */
+ USBx_HC((uint32_t)ch_num)->HCSPLT = 0U;
+ }
+
+ /* Set host channel enable */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+
+ /* make sure to set the correct ep direction */
+ if (hc->ep_is_in != 0U)
+ {
+ tmpreg |= USB_OTG_HCCHAR_EPDIR;
+ }
+ else
+ {
+ tmpreg &= ~USB_OTG_HCCHAR_EPDIR;
+ }
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+
+ if (dma != 0U) /* dma mode */
+ {
+ return HAL_OK;
+ }
+
+ if ((hc->ep_is_in == 0U) && (hc->xfer_len > 0U) && (hc->do_csplit == 0U))
+ {
+ switch (hc->ep_type)
+ {
+ /* Non periodic transfer */
+ case EP_TYPE_CTRL:
+ case EP_TYPE_BULK:
+
+ len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
+
+ /* check if there is enough space in FIFO space */
+ if (len_words > (USBx->HNPTXSTS & 0xFFFFU))
+ {
+ /* 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 = (uint16_t)((hc->xfer_len + 3U) / 4U);
+ /* check if there is enough space in FIFO space */
+ if (len_words > (USBx_HOST->HPTXSTS & 0xFFFFU)) /* 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. */
+ (void)USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, (uint16_t)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(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ return ((USBx_HOST->HAINT) & 0xFFFFU);
+}
+
+/**
+ * @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(const USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t hcnum = (uint32_t)hc_num;
+ __IO uint32_t count = 0U;
+ uint32_t HcEpType = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
+ uint32_t ChannelEna = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
+ uint32_t SplitEna = (USBx_HC(hcnum)->HCSPLT & USB_OTG_HCSPLT_SPLITEN) >> 31;
+
+ /* In buffer DMA, Channel disable must not be programmed for non-split periodic channels.
+ At the end of the next uframe/frame (in the worst case), the core generates a channel halted
+ and disables the channel automatically. */
+
+ if ((((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && (SplitEna == 0U)) &&
+ ((ChannelEna == 0U) || (((HcEpType == HCCHAR_ISOC) || (HcEpType == HCCHAR_INTR)))))
+ {
+ return HAL_OK;
+ }
+
+ /* Check for space in the request queue to issue the halt. */
+ if ((HcEpType == HCCHAR_CTRL) || (HcEpType == HCCHAR_BULK))
+ {
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
+
+ if ((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == 0U)
+ {
+ if ((USBx->HNPTXSTS & (0xFFUL << 16)) == 0U)
+ {
+ USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ do
+ {
+ count++;
+
+ if (count > 1000U)
+ {
+ break;
+ }
+ } while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+ }
+ else
+ {
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ }
+ }
+ else
+ {
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ }
+ }
+ else
+ {
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
+
+ if ((USBx_HOST->HPTXSTS & (0xFFUL << 16)) == 0U)
+ {
+ USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ do
+ {
+ count++;
+
+ if (count > 1000U)
+ {
+ break;
+ }
+ } while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+ }
+ else
+ {
+ USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
+ }
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Activate a host channel
+ * @param USBx Selected device
+ * @param ch_num Host Channel number
+ * This parameter can be a value from 1 to 15
+ * @param ch_dir Host Channel direction
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_HC_Activate(const USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num, uint8_t ch_dir)
+{
+ UNUSED(ch_dir);
+
+ __IO uint32_t tmpreg;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ /* activate the channel */
+ tmpreg = USBx_HC(ch_num)->HCCHAR;
+
+ if ((tmpreg & USB_OTG_HCCHAR_CHDIS) == 0U)
+ {
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(ch_num)->HCCHAR = tmpreg;
+ }
+
+ return HAL_OK;
+}
+#endif /* defined (HAL_HCD_MODULE_ENABLED) */
+
+/**
+ * @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(const USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ uint32_t chnum = (uint32_t)ch_num;
+ uint32_t num_packets = 1U;
+ uint32_t tmpreg;
+
+ USBx_HC(chnum)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
+ USB_OTG_HCTSIZ_DOPING;
+
+ /* Set host channel enable */
+ tmpreg = USBx_HC(chnum)->HCCHAR;
+ tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
+ tmpreg |= USB_OTG_HCCHAR_CHENA;
+ USBx_HC(chnum)->HCCHAR = tmpreg;
+
+ return HAL_OK;
+}
+
+/**
+ * @brief Stop Host Core
+ * @param USBx Selected device
+ * @retval HAL state
+ */
+HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx)
+{
+ HAL_StatusTypeDef ret = HAL_OK;
+ uint32_t USBx_BASE = (uint32_t)USBx;
+ __IO uint32_t count = 0U;
+ uint32_t value;
+ uint32_t i;
+
+ (void)USB_DisableGlobalInt(USBx);
+
+ /* Flush USB FIFO */
+ if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
+ {
+ ret = HAL_ERROR;
+ }
+
+ if (USB_FlushRxFifo(USBx) != HAL_OK)
+ {
+ ret = HAL_ERROR;
+ }
+
+ /* Flush out any leftover queued requests. */
+ for (i = 0U; i <= 15U; 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 = 0U; i <= 15U; 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
+ {
+ count++;
+
+ if (count > 1000U)
+ {
+ break;
+ }
+ } while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
+ }
+
+ /* Clear any pending Host interrupts */
+ USBx_HOST->HAINT = CLEAR_INTERRUPT_MASK;
+ USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
+
+ (void)USB_EnableGlobalInt(USBx);
+
+ return ret;
+}
+
+/**
+ * @brief USB_ActivateRemoteWakeup active remote wakeup signalling
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_ActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
+ {
+ /* active Remote wakeup signalling */
+ USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
+ }
+
+ return HAL_OK;
+}
+
+/**
+ * @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
+ * @param USBx Selected device
+ * @retval HAL status
+ */
+HAL_StatusTypeDef USB_DeActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
+{
+ uint32_t USBx_BASE = (uint32_t)USBx;
+
+ /* active Remote wakeup signalling */
+ USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
+
+ return HAL_OK;
+}
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
+#endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
+
+/**
+ * @}
+ */